mirror of
https://github.com/anope/anope.git
synced 2026-06-16 15:34:47 +02:00
Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ae4a022eb | |||
| ea8a692191 | |||
| 026d6c461d | |||
| 3cbac4bcea | |||
| e42b4c21b7 | |||
| 2464913200 | |||
| ebea728957 | |||
| 233a5bf4cd | |||
| 7019b27e59 | |||
| 70227dc882 | |||
| 6178ea644a | |||
| df7f0730dd | |||
| 331168379f | |||
| 5220963be1 | |||
| 436dab3eb8 | |||
| c3055e1cfa | |||
| a27be92e4b | |||
| faf0ad5f35 | |||
| e9202916b2 | |||
| 2cb20ded78 | |||
| 687bcaa83f | |||
| 1fb8a624f9 | |||
| b4b51d4828 | |||
| 7083c424c2 | |||
| c55d8450a4 | |||
| 7a20f26b84 | |||
| de16238e01 | |||
| 240f8b9e50 | |||
| 656ca80dd0 | |||
| d40cbdb8cf | |||
| a668c8b520 | |||
| bc44195a3d | |||
| a7cbe2a139 | |||
| 8408bf95c7 | |||
| 309c342b86 | |||
| 4de59d61d8 | |||
| 0dc65cc162 | |||
| 2e6c90d502 | |||
| 127ea3e68a | |||
| ba11b5eab0 | |||
| df1c6176b3 | |||
| 96ccfe4cbe | |||
| 8634594cd1 | |||
| ee160842b3 | |||
| 613452acba | |||
| 9411dac991 | |||
| aa32f7c926 | |||
| 517810b208 | |||
| b7f7a91dfb | |||
| b6e4c7302e | |||
| b7590e20c1 | |||
| 4952a9c852 | |||
| 59647baff9 | |||
| 1393518555 | |||
| 51827b94ad | |||
| 98c840eb02 | |||
| 24cbb84009 | |||
| f3c94e5d23 | |||
| f2ab092742 | |||
| 7d5ca5c90b | |||
| 8ee85efd70 | |||
| 0cab675825 | |||
| f1751dcb21 | |||
| 8b02613549 | |||
| c9625ccf3f | |||
| 435ce51196 | |||
| 57ac7cb4db | |||
| 8cb2b801e9 | |||
| 66b45534a8 | |||
| 499077826c | |||
| bc4d34ebd8 | |||
| f40719787f | |||
| 934a13c21f | |||
| e5602f956d | |||
| de11a19e03 | |||
| b437468b84 | |||
| 0a99571c0f | |||
| e704fa6266 | |||
| f908514095 | |||
| bafcba023c | |||
| 9a44b74186 | |||
| 883935c3e0 | |||
| 6d34054b78 | |||
| 3da9b6df0d | |||
| 0ab0e4737c | |||
| cdf356ed33 | |||
| 7d268bb4ca | |||
| 184350ff4a | |||
| 4cdbf560e1 | |||
| cbccc79d37 | |||
| 9b188a6c04 | |||
| 2f74513246 | |||
| 94dbb19593 | |||
| 8232759a92 | |||
| b006966d25 | |||
| 6037f63ae5 | |||
| 5cdb65ca52 | |||
| f9e4ca4d06 | |||
| 66c9be8627 | |||
| 546f65c38e | |||
| 9fcb022d5e | |||
| 5a0c6b1f18 | |||
| ade8db023e | |||
| 2ae733bcd1 | |||
| cc37e6d69a | |||
| 101c68f786 | |||
| ec0cd9e7f9 |
@@ -0,0 +1,44 @@
|
||||
---
|
||||
name: Bug report
|
||||
description: Report a non-security bug in Anope.
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
|
||||
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.
|
||||
|
||||
If you're reporting a crash or other security issue [please read our security policy](https://github.com/anope/anope/security/policy#reporting-a-vulnerability) for how to report security issues privately.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce the issue
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the results you received
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the results you expected
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Anope version
|
||||
description: |-
|
||||
Either the output of `services --version` (2.0) or `anope --version` (2.1).
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report a non-security issue with Anope.
|
||||
---
|
||||
|
||||
<!--
|
||||
Please fill in the template below. It will help us process your bug report a lot faster. If you have multiple bugs to report then please open one issue for each bug.
|
||||
-->
|
||||
|
||||
**Description**
|
||||
|
||||
|
||||
|
||||
**Steps to reproduce the issue:**
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
**Describe the results you received:**
|
||||
|
||||
|
||||
|
||||
**Describe the results you expected:**
|
||||
|
||||
|
||||
|
||||
**Additional information you deem important (e.g. issue happens only occasionally):**
|
||||
|
||||
|
||||
|
||||
**Output of `services --version`:**
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
description: Request that a new feature is added to Anope.
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this feature request!
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Why this would be useful?
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Request that a new feature is added to Anope.
|
||||
---
|
||||
|
||||
<!--
|
||||
Please fill in the template below. It will help us process your feature request a lot faster. If you have multiple features to request then please open one issue for each feature.
|
||||
-->
|
||||
|
||||
**Description**
|
||||
|
||||
|
||||
|
||||
**Why this would be useful**
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Support forum
|
||||
url: https://github.com/orgs/anope/discussions/categories/support
|
||||
about: Please ask support questions here.
|
||||
|
||||
+1
-1
@@ -14,6 +14,6 @@ Version | Supported
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please do not report security vulnerabilities on GitHub. Instead, email the details to team@anope.org or get the attention of a developer in our development IRC channel at irc.anope.org #anope-devel and PM them the details.
|
||||
Please do not report security vulnerabilities on GitHub. Instead, email the details to team@anope.org or get the attention of a developer in our development IRC channel at irc.teranova.net #anope-devel and PM them the details.
|
||||
|
||||
We will triage your issue as soon as possible and try to release a fixed version within a week of receiving your report.
|
||||
|
||||
@@ -14,3 +14,4 @@ modules/ssl_openssl.cpp
|
||||
modules/stats
|
||||
run/
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
@@ -4,7 +4,7 @@ Anope is an open source set of IRC services. It is highly modular, with a vast n
|
||||
|
||||
* [Website](https://anope.org)
|
||||
* [GitHub](https://github.com/anope)
|
||||
* IRC \#anope on irc.anope.org
|
||||
* IRC \#anope on irc.teranova.net
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -33,7 +33,7 @@ Copy conf/anope.example.conf to conf/anope.conf
|
||||
$ cp conf/anope.example.conf conf/anope.conf
|
||||
```
|
||||
|
||||
Edit anope.conf, configuring the uplink, serverinfo, and protocol module configurations. Example link blocks for popular IRCds are included in the anope.example.conf documentation. The [Anope wiki](https://wiki.anope.org) is also a good source of information. Our support channel is located at #anope on [irc.anope.org](irc://irc.anope.org/#anope).
|
||||
Edit anope.conf, configuring the uplink, serverinfo, and protocol module configurations. Example link blocks for popular IRCds are included in the the example.conf documentation. The [Anope wiki](https://wiki.anope.org) is also a good source of information. Our support channel is located at #anope on [irc.teranova.net](ircs://irc.teranova.net/anope).
|
||||
|
||||
Note that the example configuration file includes other example configuration files. If you want to modify the other example configuration files, copy them (e.g. `modules.example.conf` to `modules.conf`) and modify the `include` directive in `anope.conf` to include the new file.
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Only install example.chk and anope.example.conf from this directory
|
||||
# Only install cron.example.sh and anope.example.conf from this directory
|
||||
# NOTE: I would've had this just find all files in the directory, but that would include files not needed (like this file)
|
||||
set(DATA cron.example.sh anope.example.conf botserv.example.conf hostserv.example.conf modules.example.conf operserv.example.conf chanserv.example.conf global.example.conf memoserv.example.conf nickserv.example.conf chanstats.example.conf irc2sql.example.conf stats.standalone.example.conf)
|
||||
install(FILES ${DATA}
|
||||
|
||||
+8
-30
@@ -414,12 +414,6 @@ options
|
||||
*/
|
||||
readtimeout = 5s
|
||||
|
||||
/*
|
||||
* Sets the interval between sending warning messages for program errors via
|
||||
* WALLOPS/GLOBOPS.
|
||||
*/
|
||||
warningtimeout = 4h
|
||||
|
||||
/*
|
||||
* Sets the (maximum) frequency at which the timeout list is checked. This,
|
||||
* combined with readtimeout above, determines how accurately timed events,
|
||||
@@ -436,26 +430,11 @@ options
|
||||
timeoutcheck = 3s
|
||||
|
||||
/*
|
||||
* If set, this will allow users to let services send PRIVMSGs to them
|
||||
* instead of NOTICEs. Also see the "msg" option of nickserv:defaults,
|
||||
* which also toggles the default communication (PRIVMSG or NOTICE) to
|
||||
* use for unregistered users.
|
||||
*
|
||||
* This is a feature that is against the IRC RFC and should be used ONLY
|
||||
* if absolutely necessary.
|
||||
*
|
||||
* This directive is optional, and not recommended.
|
||||
* If set Anope will tell users to use a server-side alias for messaging
|
||||
* services instead of /msg. The alias for each service defaults to the
|
||||
* bot name but can be configured in the service block.
|
||||
*/
|
||||
#useprivmsg = yes
|
||||
|
||||
/*
|
||||
* If set, will force services to only respond to PRIVMSGs addresses to
|
||||
* Nick@ServerName - e.g. NickServ@example.com. This should be used in
|
||||
* conjunction with IRCd aliases. This directive is optional.
|
||||
*
|
||||
* This option will have no effect on some IRCds, such as TS6 IRCds.
|
||||
*/
|
||||
#usestrictprivmsg = yes
|
||||
#servicealias = yes
|
||||
|
||||
/*
|
||||
* If set, Anope will only show /stats o to IRC Operators. This directive
|
||||
@@ -823,8 +802,6 @@ opertype
|
||||
*
|
||||
* This can be used to automatically oper users who identify for services operator accounts, and is
|
||||
* useful for setting modes such as Plexus's user mode +N.
|
||||
*
|
||||
* Note that some IRCds, such as InspIRCd, do not allow directly setting +o, and this will not work.
|
||||
*/
|
||||
#modes = "+o"
|
||||
}
|
||||
@@ -1172,9 +1149,10 @@ module
|
||||
|
||||
/* Whether or not to import data from another database module in to SQL on startup.
|
||||
* If you enable this, be sure that the database services is configured to use is
|
||||
* empty and that another database module to import from is loaded before db_sql.
|
||||
* After you enable this and do a database import you should disable it for
|
||||
* subsequent restarts.
|
||||
* empty and that another database module to import from is loaded BEFORE db_sql.
|
||||
* After you enable this and do a database import you MUST disable it for
|
||||
* subsequent restarts. If you want to keep writing a flatfile database after the
|
||||
* SQL import is done you should load db_flatfile AFTER this module.
|
||||
*
|
||||
* Note that you can not import databases using db_sql_live. If you want to import
|
||||
* databases and use db_sql_live you should import them using db_sql, then shut down
|
||||
|
||||
@@ -59,6 +59,17 @@ service
|
||||
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
|
||||
*/
|
||||
#channels = "@#services,#mychan"
|
||||
|
||||
/*
|
||||
* The server alias that can be used to securely message this service. If
|
||||
* your IRC server does not have an alias for this service you can set this
|
||||
* to an empty string to tell users to use /msg instead.
|
||||
*
|
||||
* This setting is ignored when options:servicealias is disabled.
|
||||
*
|
||||
* Defaults to the nick of the service if not set.
|
||||
*/
|
||||
#alias = "BS"
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -334,10 +345,10 @@ privilege
|
||||
/*
|
||||
* fantasy
|
||||
*
|
||||
* Allows 'fantasist' commands to be used in channels.
|
||||
* Allows fantasy commands (e.g. !kick) to be used in channels.
|
||||
*
|
||||
* Provides the commands:
|
||||
* botserv/set/fantasy - Used for enabling or disabling BotServ's fantasist commands.
|
||||
* botserv/set/fantasy - Used for enabling or disabling BotServ's fantasy commands.
|
||||
*/
|
||||
module
|
||||
{
|
||||
|
||||
@@ -49,6 +49,17 @@ service
|
||||
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
|
||||
*/
|
||||
#channels = "@#services,#mychan"
|
||||
|
||||
/*
|
||||
* The server alias that can be used to securely message this service. If
|
||||
* your IRC server does not have an alias for this service you can set this
|
||||
* to an empty string to tell users to use /msg instead.
|
||||
*
|
||||
* This setting is ignored when options:servicealias is disabled.
|
||||
*
|
||||
* Defaults to the nick of the service if not set.
|
||||
*/
|
||||
#alias = "CS"
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -726,7 +737,7 @@ privilege
|
||||
privilege
|
||||
{
|
||||
name = "SET"
|
||||
desc = _("Allowed to set channel settings")
|
||||
desc = _("Allowed to modify channel settings")
|
||||
rank = 320
|
||||
level = 9999
|
||||
flag = "s"
|
||||
@@ -1245,7 +1256,7 @@ command { service = "ChanServ"; name = "SET NOEXPIRE"; command = "chanserv/saset
|
||||
* A field named misc_description may be given for use with help output.
|
||||
*/
|
||||
module { name = "cs_set_misc" }
|
||||
command { service = "ChanServ"; name = "SET URL"; command = "chanserv/set/misc"; misc_description = _("Associate a URL with the channel"); }
|
||||
command { service = "ChanServ"; name = "SET URL"; command = "chanserv/set/misc"; misc_description = _("Associate a URL with the channel"); misc_numeric = 328; }
|
||||
command { service = "ChanServ"; name = "SET EMAIL"; command = "chanserv/set/misc"; misc_description = _("Associate an email address with the channel"); }
|
||||
|
||||
/*
|
||||
|
||||
@@ -49,6 +49,17 @@ service
|
||||
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
|
||||
*/
|
||||
#channels = "@#services,#mychan"
|
||||
|
||||
/*
|
||||
* The server alias that can be used to securely message this service. If
|
||||
* your IRC server does not have an alias for this service you can set this
|
||||
* to an empty string to tell users to use /msg instead.
|
||||
*
|
||||
* This setting is ignored when options:servicealias is disabled.
|
||||
*
|
||||
* Defaults to the nick of the service if not set.
|
||||
*/
|
||||
#alias = "GL"
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -49,6 +49,17 @@ service
|
||||
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
|
||||
*/
|
||||
#channels = "@#services,#mychan"
|
||||
|
||||
/*
|
||||
* The server alias that can be used to securely message this service. If
|
||||
* your IRC server does not have an alias for this service you can set this
|
||||
* to an empty string to tell users to use /msg instead.
|
||||
*
|
||||
* This setting is ignored when options:servicealias is disabled.
|
||||
*
|
||||
* Defaults to the nick of the service if not set.
|
||||
*/
|
||||
#alias = "HS"
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -49,6 +49,17 @@ service
|
||||
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
|
||||
*/
|
||||
#channels = "@#services,#mychan"
|
||||
|
||||
/*
|
||||
* The server alias that can be used to securely message this service. If
|
||||
* your IRC server does not have an alias for this service you can set this
|
||||
* to an empty string to tell users to use /msg instead.
|
||||
*
|
||||
* This setting is ignored when options:servicealias is disabled.
|
||||
*
|
||||
* Defaults to the nick of the service if not set.
|
||||
*/
|
||||
#alias = "MS"
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+63
-30
@@ -49,6 +49,17 @@ service
|
||||
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
|
||||
*/
|
||||
#channels = "@#services,#mychan"
|
||||
|
||||
/*
|
||||
* The server alias that can be used to securely message this service. If
|
||||
* your IRC server does not have an alias for this service you can set this
|
||||
* to an empty string to tell users to use /msg instead.
|
||||
*
|
||||
* This setting is ignored when options:servicealias is disabled.
|
||||
*
|
||||
* Defaults to the nick of the service if not set.
|
||||
*/
|
||||
#alias = "NS"
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -106,8 +117,7 @@ module
|
||||
* - memo_mail: Notify user if they have a new memo by mail
|
||||
* - autoop: User will be automatically opped in channels they enter and have access to
|
||||
* - neverop: User can not be added to access lists
|
||||
* - msg: Messages will be sent as PRIVMSGs instead of NOTICEs, requires options:useprivmsg
|
||||
* to be enabled as well
|
||||
* - msg: Messages will be sent as PRIVMSGs instead of NOTICEs
|
||||
* - ns_keep_modes: Enables keepmodes, which retains user modes across sessions
|
||||
*
|
||||
* This directive is optional, if left blank, the options will default to memo_signon, and
|
||||
@@ -124,9 +134,9 @@ module
|
||||
/*
|
||||
* The length of time before a nick's registration expires.
|
||||
*
|
||||
* This directive is optional, but recommended. If not set, the default is 90 days.
|
||||
* This directive is optional, but recommended. If not set, the default is one year.
|
||||
*/
|
||||
expire = 90d
|
||||
expire = 1y
|
||||
|
||||
/*
|
||||
* Prevents the use of the ACCESS and CERT (excluding their LIST subcommand), DROP, FORBID, SUSPEND
|
||||
@@ -193,13 +203,17 @@ module
|
||||
releasetimeout = 1m
|
||||
|
||||
/*
|
||||
* When a user's nick is forcibly changed to enforce a "nick kill", their new nick will start
|
||||
* with this value. The rest will be made up of 6 or 7 digits.
|
||||
* Make sure this is a valid nick and Nicklen+7 is not longer than the allowed Nicklen on your ircd.
|
||||
* When a user's nick is forcibly changed to enforce nickname protection their new
|
||||
* nick will be based on this value. Any # in the value will be replaced with a random
|
||||
* number. If your IRCd has support for unique identifiers you can also set this to an
|
||||
* empty string to change a user's nick to their unique identifier.
|
||||
*
|
||||
* This directive is optional. If not set it defaults to "Guest"
|
||||
* Make sure this is a valid nick and that it is is not longer than the maximum nick
|
||||
* length on your IRCd.
|
||||
*
|
||||
* This directive is optional. If not set it defaults to "Guest####"
|
||||
*/
|
||||
guestnickprefix = "Guest"
|
||||
guestnick = "Guest####"
|
||||
|
||||
/*
|
||||
* If set, Anope does not allow ownership of nick names, only ownership of accounts.
|
||||
@@ -511,23 +525,11 @@ command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpas
|
||||
* nickserv/set/display, nickserv/saset/display - Used for setting a users display name.
|
||||
* nickserv/set/email, nickserv/saset/email - Used for setting a users email address.
|
||||
* nickserv/set/keepmodes, nickserv/saset/keepmodes - Configure whether or not services should retain a user's modes across sessions.
|
||||
* nickserv/set/kill, nickserv/saset/kill - Used for configuring nickname protection.
|
||||
* nickserv/set/message, nickserv/saset/message - Used to configure how services send messages to you.
|
||||
* nickserv/set/neverop, nickserv/saset/neverop - Used to configure whether a user can be added to access lists
|
||||
* nickserv/saset/noexpire - Used for configuring noexpire, which prevents nicks from expiring.
|
||||
* nickserv/set/password, nickserv/saset/password - Used for changing a users password.
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "ns_set"
|
||||
|
||||
/*
|
||||
* Allow the use of the IMMED option in the NickServ SET KILL command.
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
#allowkillimmed = yes
|
||||
}
|
||||
module { name = "ns_set" }
|
||||
|
||||
command { service = "NickServ"; name = "SET"; command = "nickserv/set"; }
|
||||
command { service = "NickServ"; name = "SASET"; command = "nickserv/saset"; permission = "nickserv/saset/"; group = "nickserv/admin"; }
|
||||
@@ -544,12 +546,6 @@ command { service = "NickServ"; name = "SASET EMAIL"; command = "nickserv/saset/
|
||||
command { service = "NickServ"; name = "SET KEEPMODES"; command = "nickserv/set/keepmodes"; }
|
||||
command { service = "NickServ"; name = "SASET KEEPMODES"; command = "nickserv/saset/keepmodes"; permission = "nickserv/saset/keepmodes"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/kill"; }
|
||||
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/kill"; permission = "nickserv/saset/kill"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET MESSAGE"; command = "nickserv/set/message"; }
|
||||
command { service = "NickServ"; name = "SASET MESSAGE"; command = "nickserv/saset/message"; permission = "nickserv/saset/message"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET PASSWORD"; command = "nickserv/set/password"; }
|
||||
command { service = "NickServ"; name = "SASET PASSWORD"; command = "nickserv/saset/password"; permission = "nickserv/saset/password"; }
|
||||
|
||||
@@ -558,6 +554,28 @@ command { service = "NickServ"; name = "SASET NEVEROP"; command = "nickserv/sase
|
||||
|
||||
command { service = "NickServ"; name = "SASET NOEXPIRE"; command = "nickserv/saset/noexpire"; permission = "nickserv/saset/noexpire"; }
|
||||
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
@@ -569,6 +587,21 @@ module { name = "ns_set_language" }
|
||||
command { service = "NickServ"; name = "SET LANGUAGE"; command = "nickserv/set/language"; }
|
||||
command { service = "NickServ"; name = "SASET LANGUAGE"; command = "nickserv/saset/language"; permission = "nickserv/saset/language"; }
|
||||
|
||||
/*
|
||||
* ns_set_message
|
||||
*
|
||||
* Provides the commands nickserv/set/message and nickserv/saset/message.
|
||||
*
|
||||
* Allows users to let services send them PRIVMSGs instead of NOTICEs.
|
||||
*
|
||||
* This might cause problems with badly written clients as the IRC RFC
|
||||
* requires that automatic responses to a PRIVMSG use a NOTICE to avoid
|
||||
* message loops. Only enable this if you are sure this can not happen.
|
||||
*/
|
||||
#module { name = "ns_set_message" }
|
||||
#command { service = "NickServ"; name = "SET MESSAGE"; command = "nickserv/set/message"; }
|
||||
#command { service = "NickServ"; name = "SASET MESSAGE"; command = "nickserv/saset/message"; permission = "nickserv/saset/message"; }
|
||||
|
||||
/*
|
||||
* ns_set_misc
|
||||
*
|
||||
@@ -582,10 +615,10 @@ command { service = "NickServ"; name = "SET URL"; command = "nickserv/set/misc";
|
||||
command { service = "NickServ"; name = "SASET URL"; command = "nickserv/saset/misc"; misc_description = _("Associate a URL with this account"); permission = "nickserv/saset/url"; group = "nickserv/admin"; }
|
||||
#command { service = "NickServ"; name = "SET DISCORD"; command = "nickserv/set/misc"; misc_description = _("Associate a Discord account with your account"); }
|
||||
#command { service = "NickServ"; name = "SASET DISCORD"; command = "nickserv/saset/misc"; misc_description = _("Associate a Discord account with this account"); permission = "nickserv/saset/discord"; group = "nickserv/admin"; }
|
||||
#command { service = "NickServ"; name = "SET FACEBOOK"; command = "nickserv/set/misc"; misc_description = _("Associate a Facebook URL with your account"); }
|
||||
#command { service = "NickServ"; name = "SASET FACEBOOK"; command = "nickserv/saset/misc"; misc_description = _("Associate a Facebook URL with this account"); permission = "nickserv/saset/facebook"; group = "nickserv/admin"; }
|
||||
#command { service = "NickServ"; name = "SET MASTODON"; command = "nickserv/set/misc"; misc_description = _("Associate a Mastodon account with your account"); }
|
||||
#command { service = "NickServ"; name = "SASET MASTODON"; command = "nickserv/saset/misc"; misc_description = _("Associate a Mastodon account with this account"); permission = "nickserv/saset/mastodon"; group = "nickserv/admin"; }
|
||||
#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_suspend
|
||||
|
||||
@@ -49,6 +49,17 @@ service
|
||||
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
|
||||
*/
|
||||
#channels = "@#services,#mychan"
|
||||
|
||||
/*
|
||||
* The server alias that can be used to securely message this service. If
|
||||
* your IRC server does not have an alias for this service you can set this
|
||||
* to an empty string to tell users to use /msg instead.
|
||||
*
|
||||
* This setting is ignored when options:servicealias is disabled.
|
||||
*
|
||||
* Defaults to the nick of the service if not set.
|
||||
*/
|
||||
#alias = "OS"
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -371,12 +371,6 @@ options
|
||||
*/
|
||||
readtimeout = 5s
|
||||
|
||||
/*
|
||||
* Sets the interval between sending warning messages for program errors via
|
||||
* WALLOPS/GLOBOPS.
|
||||
*/
|
||||
warningtimeout = 4h
|
||||
|
||||
/*
|
||||
* If set, Anope will only show /stats o to IRC Operators. This directive
|
||||
* is optional.
|
||||
|
||||
@@ -1,3 +1,38 @@
|
||||
Anope Version 2.1.11
|
||||
--------------------
|
||||
Added support for database migrations to the mysql module.
|
||||
Added support for renicking users to their UID when enforcing nickname protection.
|
||||
Added support for sending channel URLs to joining users.
|
||||
Allowed selecting languages using a shorter version of their name.
|
||||
Changed various messages to use human-readable durations instead of seconds.
|
||||
Improved the creation of expiry and duration messages.
|
||||
Improved the translation system with support for plural forms.
|
||||
Reworked how guest nicknames are generated.
|
||||
Simplified how account identifiers are allocated.
|
||||
|
||||
Anope Version 2.1.10
|
||||
--------------------
|
||||
Added support for NEXTBANS on UnrealIRCd.
|
||||
Changed hostmask access entries added by nick to use that nick as the default description.
|
||||
Changed modes to be handled internally in their split form.
|
||||
Changed ns_cert to notify a user that their certificate is being automatically added to their account.
|
||||
Fixed matching users against extended bans.
|
||||
Fixed parsing name-only extended bans on InspIRCd.
|
||||
Fixed respecting the preferred extended ban format on InspIRCd.
|
||||
Fixed the name of the cron script in the docs.
|
||||
Updated the list of supported IRCds.
|
||||
Updated the location of the Anope IRC channels
|
||||
|
||||
Anope Version 2.1.9
|
||||
-------------------
|
||||
Bumped the minimum supported version of UnrealIRCd to 6.
|
||||
Fixed granting IRC operator status to services operators.
|
||||
Fixed making users an IRC operator on InspIRCd.
|
||||
Fixed nonicknameownership on InspIRCd v4.
|
||||
Fixed some messages not being translatable.
|
||||
Fixed the Argon2 module not having test vectors.
|
||||
Increased the default nickname expiry period to one year.
|
||||
|
||||
Anope Version 2.1.8
|
||||
-------------------
|
||||
Added account identifiers to the nickserv/info output.
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
Anope Version 2.1.11
|
||||
--------------------
|
||||
Moved module:allowkilimmed from the ns_set module to the ns_set_kill module.
|
||||
Moved nickserv/set/kill and nickserv/saset/kill to the ns_set_kill module.
|
||||
Replaced module:guestnickprefix for the nickserv module with module:guestnick.
|
||||
|
||||
Anope Version 2.1.10
|
||||
--------------------
|
||||
Added options:servicealias.
|
||||
Moved nickserv/set/message and nickserv/saset/message to the ns_set_message module.
|
||||
Removed options:useprivmsg.
|
||||
Removed options:usestrictprivmsg
|
||||
|
||||
Anope Version 2.1.9
|
||||
-------------------
|
||||
No significant changes.
|
||||
|
||||
Anope Version 2.1.8
|
||||
-------------------
|
||||
Added module:preservedisplay to the nickserv module.
|
||||
|
||||
+1
-1
@@ -90,4 +90,4 @@ Anope DefCon
|
||||
6) Support
|
||||
|
||||
You might get DefCon support by posting on our online forum, or maybe on
|
||||
our #anope channel at /server irc.anope.org.
|
||||
our #anope channel at /server irc.teranova.net.
|
||||
|
||||
+5
-5
@@ -60,7 +60,7 @@ Note: You should also read the README and FAQ files!
|
||||
most likely not work!
|
||||
|
||||
If you need help, you should visit https://forum.anope.org/ or #anope on
|
||||
irc.anope.org. Provide *complete* error output, along with other relevant
|
||||
irc.teranova.net. Provide *complete* error output, along with other relevant
|
||||
information eg. OS, compiler and C++ library versions.
|
||||
See the README file for more information.
|
||||
|
||||
@@ -111,17 +111,17 @@ Note: You should also read the README and FAQ files!
|
||||
A crontab entry will allow you to check periodically whether Anope is
|
||||
still running, and restart it if not.
|
||||
|
||||
First rename the example.chk script that is in Anope path (by default,
|
||||
this is ~/anope/conf) to anope.chk and edit it. You'll need to
|
||||
First rename the cron.example.sh script that is in Anope path (by default,
|
||||
this is ~/anope/conf) to cron.sh and edit it. You'll need to
|
||||
modify the CONFIGURATION part of the file. Then ensure that the file is
|
||||
marked as executable by typing chmod +x anope.chk, and try to launch the
|
||||
marked as executable by typing chmod +x cron.sh, and try to launch the
|
||||
script to see if it works (Anope must not be running when you do this ;))
|
||||
|
||||
When this is done, you'll have to add the crontab entry. Type crontab -e.
|
||||
This will open the default text editor with the crontab file. Enter the
|
||||
following (with correct path):
|
||||
|
||||
*/5 * * * * /home/ircd/anope/conf/anope.chk >/dev/null 2>&1
|
||||
*/5 * * * * /home/ircd/anope/conf/cron.sh >/dev/null 2>&1
|
||||
|
||||
The */5 at the beginning means "check every 5 minutes". You may replace
|
||||
the 5 with other another number if you want (but less than 60). Consult
|
||||
|
||||
+5
-5
@@ -64,7 +64,7 @@ Note : Vous devrez également lire les fichiers README et FAQ !
|
||||
recommandée, et Anope ne fonctionnera probablement pas !
|
||||
|
||||
Si vous avez besoin d'aide, vous pouvez aller sur le site
|
||||
https://forum.anope.org/ ou le canal #anope sur irc.anope.org.
|
||||
https://forum.anope.org/ ou le canal #anope sur irc.teranova.net.
|
||||
Fournissez *l'essemble* des erreurs qui apparaîssent, en plus de
|
||||
toutes informations utiles, comme les versions de votre OS, du
|
||||
compilateur utilisé et de la librairie C++. Lisez le fichier README
|
||||
@@ -121,11 +121,11 @@ Note : Vous devrez également lire les fichiers README et FAQ !
|
||||
Une entrée crontab vous permettra de vérifier périodiquement si Anope
|
||||
est toujours en cours d'exécution et de le redémarrer s'il n'est pas.
|
||||
|
||||
D'abord renommez le script example.chk qui est dans les dossiers
|
||||
d'Anope (par défaut, ~/anope/conf) en anope.chk et modifiez-le.
|
||||
D'abord renommez le script cron.example.sh qui est dans les dossiers
|
||||
d'Anope (par défaut, ~/anope/conf) en cron.sh et modifiez-le.
|
||||
Vous aurez besoin de modifier la partie CONFIGURATION du fichier.
|
||||
Assurez-vous ensuite que le fichier est marqué comme exécutable en
|
||||
tapant chmod +x anope.chk et essayez de lancer le script pour voir
|
||||
tapant chmod +x cron.sh et essayez de lancer le script pour voir
|
||||
si cela fonctionne (Anope ne doit pas être en marche lorsque vous
|
||||
testez cela ;))
|
||||
|
||||
@@ -133,7 +133,7 @@ Note : Vous devrez également lire les fichiers README et FAQ !
|
||||
crontab -e. Cela va ouvrir l'éditeur de texte par défaut avec le
|
||||
fichier crontab. Entrez la ligne suivante (avec le chemin correct) :
|
||||
|
||||
*/5 * * * * /home/ircd/anope/conf/anope.chk > /dev/null 2>&1
|
||||
*/5 * * * * /home/ircd/anope/conf/cron.sh > /dev/null 2>&1
|
||||
|
||||
Le */5 au début signifie "vérifier toutes les 5 minutes". Vous pouvez
|
||||
remplacer le 5 par un autre numéro si vous voulez (mais moins de 60).
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ Anope Modules
|
||||
Use modules at your own risk, and make sure you get them from a
|
||||
reputable source. You might get module support by contacting the module
|
||||
author, posting on our online forum, or maybe on our #anope channel
|
||||
at /server irc.anope.org.
|
||||
at /server irc.teranova.net.
|
||||
|
||||
7) Information for Developers
|
||||
|
||||
|
||||
+4
-4
@@ -167,13 +167,13 @@ Table of Contents
|
||||
Anope currently works with:
|
||||
|
||||
* Bahamut 2.0 or later
|
||||
* ircd-hybrid 8.2.23 or later
|
||||
* InspIRCd 3 or later
|
||||
* ircd-hybrid 8.2.23 or later
|
||||
* ircd-ratbox 3 or later
|
||||
* ngIRCd 19.2 or later
|
||||
* Plexus 3 or later
|
||||
* Ratbox 2.0.6 or later
|
||||
* Solanum (all versions)
|
||||
* UnrealIRCd 4 or later
|
||||
* UnrealIRCd 6 or later
|
||||
|
||||
Anope could also work with some of the daemons derived by the ones listed
|
||||
above, but there's no support for them if they work or don't work.
|
||||
@@ -245,7 +245,7 @@ Table of Contents
|
||||
|
||||
If you read the documentation carefully, and didn't find the answer to
|
||||
your question, feel free to post on the website forums or join our irc
|
||||
channel (irc.anope.org #anope). Once you join our Support channel be as
|
||||
channel (irc.teranova.net #anope). Once you join our Support channel be as
|
||||
precise as possible when asking a question, because we have no extraordinary
|
||||
powers and can't guess things if they aren't provided.
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ typedef std::unordered_map<uint64_t, NickCore *> nickcoreid_map;
|
||||
|
||||
extern CoreExport Serialize::Checker<nickalias_map> NickAliasList;
|
||||
extern CoreExport Serialize::Checker<nickcore_map> NickCoreList;
|
||||
extern CoreExport nickcoreid_map NickCoreIdList;
|
||||
extern CoreExport Serialize::Checker<nickcoreid_map> NickCoreIdList;
|
||||
|
||||
/* A registered nickname.
|
||||
* It matters that Base is here before Extensible (it is inherited by Serializable)
|
||||
|
||||
@@ -473,13 +473,6 @@ namespace Anope
|
||||
*/
|
||||
extern CoreExport bool Encrypt(const Anope::string &src, Anope::string &dest);
|
||||
|
||||
/** Hashes a buffer with SipHash-2-4
|
||||
* @param src The start of the buffer to hash
|
||||
* @param src_sz The total number of bytes in the buffer
|
||||
* @param key A 16 byte key to hash the buffer with.
|
||||
*/
|
||||
extern CoreExport uint64_t SipHash24(const void *src, unsigned long src_sz, const char key[16]);
|
||||
|
||||
/** Returns a sequence of data formatted as the format argument specifies.
|
||||
** After the format parameter, the function expects at least as many
|
||||
** additional arguments as specified in format.
|
||||
|
||||
@@ -31,6 +31,8 @@ public:
|
||||
time_t lastmsg;
|
||||
/* Map of actual command names -> service name/permission required */
|
||||
CommandInfo::map commands;
|
||||
/* The server-side alias used to message this bot. */
|
||||
Anope::string alias;
|
||||
/* Modes the bot should have as configured in service:modes */
|
||||
Anope::string botmodes;
|
||||
/* Channels the bot should be in as configured in service:channels */
|
||||
@@ -126,6 +128,9 @@ 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;
|
||||
|
||||
/** Find a bot by nick
|
||||
* @param nick The nick
|
||||
* @param nick_only True to only look by nick, and not by UID
|
||||
|
||||
+1
-1
@@ -215,7 +215,7 @@ public:
|
||||
* @param mode the modes
|
||||
* @param enforce_mlock true to enforce mlock
|
||||
*/
|
||||
void SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts = 0, bool enforce_mlock = true);
|
||||
void SetModesInternal(MessageSource &source, const Anope::string &modes, const std::vector<Anope::string> ¶ms, time_t ts = 0, bool enforce_mlock = true);
|
||||
|
||||
/** Does the given user match the given list? (CMODE_BAN, CMODE_EXCEPT, etc, a list mode)
|
||||
* @param u The user
|
||||
|
||||
@@ -81,6 +81,7 @@ public:
|
||||
bool IsFounder(ChannelInfo *ci);
|
||||
|
||||
void Reply(const char *message, ...) ATTR_FORMAT(2, 3);
|
||||
void Reply(int count, const char *singular, const char *plural, ...) ATTR_FORMAT(4, 5);
|
||||
void Reply(const Anope::string &message);
|
||||
|
||||
bool HasCommand(const Anope::string &cmd);
|
||||
|
||||
+3
-7
@@ -88,21 +88,17 @@ namespace Configuration
|
||||
{
|
||||
/* options:readtimeout */
|
||||
time_t ReadTimeout;
|
||||
/* options:useprivmsg */
|
||||
bool UsePrivmsg;
|
||||
/* If we should default to privmsging clients */
|
||||
bool DefPrivmsg;
|
||||
/* Default language */
|
||||
Anope::string DefLanguage;
|
||||
/* options:timeoutcheck */
|
||||
time_t TimeoutCheck;
|
||||
/* options:usestrictprivmsg */
|
||||
bool UseStrictPrivmsg;
|
||||
/* options:servicealias */
|
||||
bool ServiceAlias;
|
||||
/* networkinfo:nickchars */
|
||||
Anope::string NickChars;
|
||||
|
||||
/* either "/msg " or "/" */
|
||||
Anope::string StrictPrivmsg;
|
||||
/* List of uplink servers to try and connect to */
|
||||
std::vector<Uplink> Uplinks;
|
||||
/* A vector of our logfile options */
|
||||
@@ -130,7 +126,7 @@ namespace Configuration
|
||||
void LoadConf(File &file);
|
||||
void Post(Conf *old);
|
||||
|
||||
Block *GetModule(Module *);
|
||||
Block *GetModule(const Module *);
|
||||
Block *GetModule(const Anope::string &name);
|
||||
|
||||
BotInfo *GetClient(const Anope::string &name);
|
||||
|
||||
@@ -194,7 +194,7 @@ public:
|
||||
|
||||
void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
|
||||
{
|
||||
data.Store(this->name, true);
|
||||
data.Store(this->name, this->HasExt(e));
|
||||
}
|
||||
|
||||
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
|
||||
|
||||
+41
-6
@@ -55,19 +55,54 @@ namespace Language
|
||||
*/
|
||||
extern CoreExport const char *Translate(const NickCore *nc, const char *string);
|
||||
|
||||
/** Translatesa string to the given language.
|
||||
/** Translates a string to the given language.
|
||||
* @param lang The language to translate to
|
||||
* @param string The string to translate
|
||||
* @return The translated string if found, else the original string.
|
||||
*/
|
||||
extern CoreExport const char *Translate(const char *lang, const char *string);
|
||||
|
||||
/** Translates a plural string to the default language.
|
||||
* @param count The number of items the string is counting.
|
||||
* @param singular The string to translate if there is one of \p count
|
||||
* @param plural The string to translate if there is multiple of \p count
|
||||
* @return The translated string if found, else the original string.
|
||||
*/
|
||||
extern CoreExport const char *Translate(int count, const char *singular, const char *plural);
|
||||
|
||||
/** Translates a plural string to the language of the given user.
|
||||
* @param u The user to translate the string for
|
||||
* @param count The number of items the string is counting.
|
||||
* @param singular The string to translate if there is one of \p count
|
||||
* @param plural The string to translate if there is multiple of \p count
|
||||
* @return The translated string if found, else the original string.
|
||||
*/
|
||||
extern CoreExport const char *Translate(User *u, int count, const char *singular, const char *plural);
|
||||
|
||||
/** Translates a plural string to the language of the given account.
|
||||
* @param nc The account to translate the string for
|
||||
* @param count The number of items the string is counting.
|
||||
* @param singular The string to translate if there is one of \p count
|
||||
* @param plural The string to translate if there is multiple of \p count
|
||||
* @return The translated string if count, else the original string
|
||||
*/
|
||||
extern CoreExport const char *Translate(const NickCore *nc, int count, const char *singular, const char *plural);
|
||||
|
||||
/** Translates a plural string to the given language.
|
||||
* @param lang The language to translate to
|
||||
* @param count The number of items the string is counting.
|
||||
* @param singular The string to translate if there is one of \p count
|
||||
* @param plural The string to translate if there is multiple of \p count
|
||||
* @return The translated string if found, else the original string.
|
||||
*/
|
||||
extern CoreExport const char *Translate(const char *lang, int count, const char *singular, const char *plural);
|
||||
|
||||
} // namespace Language
|
||||
|
||||
/* Commonly used language strings */
|
||||
#define CONFIRM_DROP _("Please confirm that you want to drop \002%s\002 with \002%s%s DROP %s %s\002")
|
||||
#define CONFIRM_DROP _("Please confirm that you want to drop \002%s\002 with \002%s DROP %s %s\002")
|
||||
#define SERVICE_UNAVAILABLE _("Sorry, %s is temporarily unavailable.")
|
||||
#define MORE_INFO _("\002%s%s HELP %s\002 for more information.")
|
||||
#define MORE_INFO _("\002%s HELP %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.")
|
||||
@@ -93,7 +128,7 @@ namespace Language
|
||||
#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%s IDENTIFY \037password\037\002. Otherwise,\n" \
|
||||
"nick, type \002%s IDENTIFY \037password\037\002. Otherwise,\n" \
|
||||
"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.")
|
||||
@@ -111,9 +146,9 @@ namespace Language
|
||||
#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%s READ %s %zu\002 to read it.")
|
||||
"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%s READ %zu\002 to read it.")
|
||||
"Type \002%s READ %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.")
|
||||
|
||||
+3
-2
@@ -66,10 +66,11 @@ namespace Message
|
||||
* @param source The source of the SJOIN
|
||||
* @param chan The channel the users are joining to
|
||||
* @param ts The TS for the channel
|
||||
* @param modes The modes sent with the SJOIN, if any
|
||||
* @param modes The mode letters sent with the SJOIN, if any
|
||||
* @param modeparams The mode parameters sent with the SJOIN, if any
|
||||
* @param users The users and their status, if any
|
||||
*/
|
||||
static void SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::list<SJoinUser> &users);
|
||||
static void SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::vector<Anope::string> &modeparams, const std::list<SJoinUser> &users);
|
||||
};
|
||||
|
||||
struct CoreExport Kick
|
||||
|
||||
+4
-1
@@ -216,9 +216,12 @@ template<typename T>
|
||||
class CoreExport ChannelModeVirtual
|
||||
: public T
|
||||
{
|
||||
Anope::string base;
|
||||
private:
|
||||
ChannelMode *basech;
|
||||
|
||||
protected:
|
||||
Anope::string base;
|
||||
|
||||
public:
|
||||
ChannelModeVirtual(const Anope::string &mname, const Anope::string &basename);
|
||||
|
||||
|
||||
@@ -19,4 +19,5 @@ public:
|
||||
virtual void Validate(User *u) = 0;
|
||||
virtual void Collide(User *u, NickAlias *na) = 0;
|
||||
virtual void Release(NickAlias *na) = 0;
|
||||
virtual bool IsGuestNick(const Anope::string &nick) const = 0;
|
||||
};
|
||||
|
||||
+1
-3
@@ -98,10 +98,8 @@ public:
|
||||
|
||||
void Register()
|
||||
{
|
||||
std::map<Anope::string, Service *> &smap = Services[this->type];
|
||||
if (smap.find(this->name) != smap.end())
|
||||
if (!Services[this->type].emplace(this->name, this).second)
|
||||
throw ModuleException("Service " + this->type + " with name " + this->name + " already exists");
|
||||
smap[this->name] = this;
|
||||
}
|
||||
|
||||
void Unregister()
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#define BUFSIZE 1024
|
||||
|
||||
#define _(x) x
|
||||
#define N_(x, y) x, y
|
||||
|
||||
#ifndef _WIN32
|
||||
# define DllExport __attribute__ ((visibility ("default")))
|
||||
|
||||
+4
-4
@@ -164,15 +164,15 @@ public:
|
||||
* @param sz How much to read
|
||||
* @return Number of bytes received
|
||||
*/
|
||||
virtual int Recv(Socket *s, char *buf, size_t sz);
|
||||
virtual ssize_t Recv(Socket *s, char *buf, size_t sz);
|
||||
|
||||
/** Write something to the socket
|
||||
* @param s The socket
|
||||
* @param buf The data to write
|
||||
* @param size The length of the data
|
||||
*/
|
||||
virtual int Send(Socket *s, const char *buf, size_t sz);
|
||||
int Send(Socket *s, const Anope::string &buf);
|
||||
virtual ssize_t Send(Socket *s, const char *buf, size_t sz);
|
||||
ssize_t Send(Socket *s, const Anope::string &buf);
|
||||
|
||||
/** Accept a connection from a socket
|
||||
* @param s The socket
|
||||
@@ -503,7 +503,7 @@ public:
|
||||
* @param sz The size of the buffer
|
||||
* @return The amount of data read
|
||||
*/
|
||||
int Read(char *data, size_t sz);
|
||||
ssize_t Read(char *data, size_t sz);
|
||||
|
||||
/** Mark the write end of this pipe (non)blocking
|
||||
* @param state true to enable blocking, false to disable blocking
|
||||
|
||||
+6
-5
@@ -107,14 +107,14 @@ protected:
|
||||
* @param suid The unique identifier of the user.
|
||||
* @param nc The account the user is identified as, if any
|
||||
*/
|
||||
User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc);
|
||||
User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const std::vector<Anope::string> &smodeparams, const Anope::string &suid, NickCore *nc);
|
||||
|
||||
/** Destroy a user.
|
||||
*/
|
||||
virtual ~User();
|
||||
|
||||
public:
|
||||
static User *OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc);
|
||||
static User *OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc, const std::vector<Anope::string> &smodeparams = {});
|
||||
|
||||
/** Update the nickname of a user record accordingly, should be
|
||||
* called from ircd protocol.
|
||||
@@ -190,6 +190,7 @@ public:
|
||||
* @param ... any number of parameters
|
||||
*/
|
||||
void SendMessage(BotInfo *source, const char *fmt, ...) ATTR_FORMAT(3, 4);
|
||||
void SendMessage(BotInfo *source, int count, const char *singular, const char *plural, ...) ATTR_FORMAT(5, 6);
|
||||
void SendMessage(BotInfo *source, const Anope::string &msg) override;
|
||||
void SendMessage(CommandSource &source, const Anope::string &msg) override;
|
||||
|
||||
@@ -307,10 +308,10 @@ public:
|
||||
|
||||
/** Set a string of modes on a user internally
|
||||
* @param setter who/what is setting the mode
|
||||
* @param umodes The modes
|
||||
* @param umodes The mode letters
|
||||
* @param umodeparams The mode values
|
||||
*/
|
||||
void SetModesInternal(const MessageSource &source, const char *umodes, ...) ATTR_FORMAT(3, 4);
|
||||
void SetModesInternal(const MessageSource &source, const Anope::string &umodes);
|
||||
void SetModesInternal(const MessageSource &source, const Anope::string &umodes, const std::vector<Anope::string> &umodeparams = {});
|
||||
|
||||
/** Get modes set for this user.
|
||||
* @return A string of modes set on the user
|
||||
|
||||
+1567
-3058
File diff suppressed because it is too large
Load Diff
+485
-600
File diff suppressed because it is too large
Load Diff
+534
-273
File diff suppressed because it is too large
Load Diff
+97
-86
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Anope\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-23 18:32+0100\n"
|
||||
"PO-Revision-Date: 2024-06-23 16:07+0300\n"
|
||||
"POT-Creation-Date: 2024-11-11 21:27+0000\n"
|
||||
"PO-Revision-Date: 2024-11-11 22:30+0300\n"
|
||||
"Last-Translator: CaPaCuL <capacul@gmail.com>\n"
|
||||
"Language-Team: Turkish\n"
|
||||
"Language: tr_TR\n"
|
||||
@@ -16,7 +16,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 3.4.4\n"
|
||||
"X-Generator: Poedit 3.5\n"
|
||||
|
||||
#, c-format
|
||||
msgid "%d channel(s) cleared, and %d channel(s) dropped."
|
||||
@@ -81,47 +81,47 @@ msgid ""
|
||||
"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 %s%s command. For\n"
|
||||
"below; to use them, type %s command. For\n"
|
||||
"more information on a specific command, type\n"
|
||||
"%s%s %s command.\n"
|
||||
"%s %s command.\n"
|
||||
msgstr ""
|
||||
"%s kendi kanalınızda bir bot bulundurmanıza olanak tanır.\n"
|
||||
"Bir botu barındıramayan veya yapılandıramayan kullanıcılar için ya da\n"
|
||||
"kullanıcı botlarına izin vermeyen ağlarda kullanılmak üzere\n"
|
||||
"oluşturulmuştur. Mevcut komutlar aşağıdaki listelendi;\n"
|
||||
"bunları kullanmak için %s%s komut yazın.\n"
|
||||
"Belirli bir komut hakkında daha fazla bilgi için şunu yazın:\n"
|
||||
"%s%s %s komut.\n"
|
||||
"bunları kullanmak için %s komut yazın.\n"
|
||||
"Belirli bir komut hakkında daha fazla bilgi için,\n"
|
||||
"%s %s komut yazın.\n"
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s allows you to register a nickname and\n"
|
||||
"prevent others from using it. The following\n"
|
||||
"commands allow for registration and maintenance of\n"
|
||||
"nicknames; to use them, type %s%s command.\n"
|
||||
"nicknames; to use them, type %s command.\n"
|
||||
"For more information on a specific command, type\n"
|
||||
"%s%s %s command.\n"
|
||||
"%s %s command.\n"
|
||||
msgstr ""
|
||||
"%s bir rumuz kaydetmenizi ve başkalarının\n"
|
||||
"bunu kullanmasının engellenmesini sağlar. Aşağıdaki\n"
|
||||
"komutlar rumuz kaydı ve düzenlemesşne izin verir;\n"
|
||||
"bunları kullanmak için %s%s komut yazın.\n"
|
||||
"bunları kullanmak için %s komut yazın.\n"
|
||||
"Belirli bir komut hakkında daha fazla bilgi için şunu yazın:\n"
|
||||
"%s%s %s komut.\n"
|
||||
"%s %s komut.\n"
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s allows you to register an account.\n"
|
||||
"The following commands allow for registration and maintenance of\n"
|
||||
"accounts; to use them, type %s%s command.\n"
|
||||
"accounts; to use them, type %s command.\n"
|
||||
"For more information on a specific command, type\n"
|
||||
"%s%s %s command.\n"
|
||||
"%s %s command.\n"
|
||||
msgstr ""
|
||||
"%s bir hesap kaydetmenizi sağlar. Aşağıdaki komutlar\n"
|
||||
"hesap kaydı ve düzenlenmesine yapılmasına izin verir; bunları\n"
|
||||
"kullanmak için %s%s komut yazın. Belirli bir\n"
|
||||
"kullanmak için %s komut yazın. Belirli bir\n"
|
||||
"komut hakkında daha fazla bilgi için şunu yazın:\n"
|
||||
"%s%s %s komut.\n"
|
||||
"%s %s komut.\n"
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
@@ -130,16 +130,16 @@ msgid ""
|
||||
"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"
|
||||
"%s%s command. For more information on a\n"
|
||||
"specific command, type %s%s HELP command.\n"
|
||||
"%s command. For more information on a\n"
|
||||
"specific command, type %s HELP command.\n"
|
||||
msgstr ""
|
||||
"%s kanalların çeşitli yönlerini kaydetmenize ve kontrol\n"
|
||||
"etmenize olanak tanır. %s, kanal operatörü ayrıcalıklarına izin verilen\n"
|
||||
"kişileri sınırlayarak, genellikle kötü niyetli kullanıcıların kanalları\n"
|
||||
"\"ele geçirmesini\" engelleyebilir. Mevcut komutlar aşağıda listelenmiştir;\n"
|
||||
"bunları kullanmak için %s%s komut yazın.\n"
|
||||
"bunları kullanmak için %s komut yazın.\n"
|
||||
"Belirli bir komut hakkında daha fazla bilgi için\n"
|
||||
"%s%s HELP komut yazın.\n"
|
||||
"%s HELP komut yazın.\n"
|
||||
|
||||
#, c-format
|
||||
msgid "%s already exists in %s bad words list."
|
||||
@@ -386,8 +386,8 @@ msgid "%s will now permanently be ignored."
|
||||
msgstr "%s artık kalıcı olarak yok sayılacak."
|
||||
|
||||
#, c-format
|
||||
msgid "%s%s HELP %s for more information."
|
||||
msgstr "Daha fazla bilgi için %s%s HELP %s."
|
||||
msgid "%s HELP %s for more information."
|
||||
msgstr "Daha fazla bilgi için %s HELP %s."
|
||||
|
||||
msgid "ADD nick user host real"
|
||||
msgstr "ADD rumuz kullanıcı host gerçek_ad"
|
||||
@@ -457,11 +457,11 @@ msgstr ""
|
||||
#, c-format
|
||||
msgid ""
|
||||
"User access levels can be seen by using the\n"
|
||||
"%s command; type %s%s HELP LEVELS for\n"
|
||||
"%s command; type %s HELP LEVELS for\n"
|
||||
"information."
|
||||
msgstr ""
|
||||
"Kullanıcı erişim düzeyleri %s komutu\n"
|
||||
"kullanılarak görülebilir; bilgi için %s%s HELP LEVELS\n"
|
||||
"kullanılarak görülebilir; bilgi için %s HELP LEVELS\n"
|
||||
"yazın."
|
||||
|
||||
#, c-format
|
||||
@@ -865,9 +865,9 @@ msgid ""
|
||||
"fantasy commands on a channel when prefixed\n"
|
||||
"with one of the following fantasy characters: %s\n"
|
||||
" \n"
|
||||
"Note that users wanting to use fantaisist\n"
|
||||
"commands MUST have enough access for both\n"
|
||||
"the FANTASIA and the command they are executing."
|
||||
"Note that users wanting to use fantasy commands\n"
|
||||
"MUST have enough access for both the FANTASY\n"
|
||||
"privilege and the command they are executing."
|
||||
msgstr ""
|
||||
" \n"
|
||||
"Bir kanalda fantezi modunu etkinleştirir veya devre dışı bırakır.\n"
|
||||
@@ -946,14 +946,14 @@ msgstr ""
|
||||
#, c-format
|
||||
msgid ""
|
||||
" \n"
|
||||
"See the %s command (%s%s HELP ACCESS) for\n"
|
||||
"See the %s command (%s HELP ACCESS) for\n"
|
||||
"information on giving a subset of these privileges to\n"
|
||||
"other channel users.\n"
|
||||
msgstr ""
|
||||
" \n"
|
||||
"Bu ayrıcalıkların bir alt kümesini diğer kanal kullanıcılarına verme\n"
|
||||
"hakkında bilgi için %s komutuna\n"
|
||||
"(%s%s HELP ACCESS) bakın.\n"
|
||||
"(%s HELP ACCESS) bakın.\n"
|
||||
|
||||
msgid ""
|
||||
" \n"
|
||||
@@ -1218,12 +1218,12 @@ msgstr ""
|
||||
#, c-format
|
||||
msgid ""
|
||||
" \n"
|
||||
"Type %s%s HELP command for help on any of the\n"
|
||||
"Type %s HELP command for help on any of the\n"
|
||||
"above commands."
|
||||
msgstr ""
|
||||
" \n"
|
||||
"Yukarıdaki komutlardan herhangi biri hakkında yardım almak için\n"
|
||||
"%s%s HELP komut yazın."
|
||||
"%s HELP komut yazın."
|
||||
|
||||
#, c-format
|
||||
msgid " %s is online using this oper block."
|
||||
@@ -1248,10 +1248,6 @@ msgstr " Yüklenme zamanı: %p"
|
||||
msgid " but %s mysteriously dematerialized."
|
||||
msgstr " ama nedendir bilinmez %s artık yok."
|
||||
|
||||
#, c-format
|
||||
msgid "\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
|
||||
msgstr "\"/msg %s\" artık desteklenmiyor. Bunun yerine \"/msg %s@%s\" ve ya \"/%s\" kullanın."
|
||||
|
||||
msgid "\"Jupiter\" a server"
|
||||
msgstr "Bir sunucuyu \"Jupiter\" yapın"
|
||||
|
||||
@@ -1811,6 +1807,9 @@ msgstr "Hesap"
|
||||
msgid "Account %s has already reached the maximum number of simultaneous logins (%u)."
|
||||
msgstr "%s hesabı zaten maksimum eşzamanlı oturum açma sayısına (%u) ulaştı."
|
||||
|
||||
msgid "Account id"
|
||||
msgstr "Hesap ID"
|
||||
|
||||
msgid "Account registered"
|
||||
msgstr "Hesap kaydedildi"
|
||||
|
||||
@@ -2015,15 +2014,15 @@ msgstr "Kanal kurucularıyla sınırlı komutlar verme izni var"
|
||||
msgid "Allowed to modify channel badwords list"
|
||||
msgstr "Kanalın küfür listesini değiştirme izni var"
|
||||
|
||||
msgid "Allowed to modify channel settings"
|
||||
msgstr "Kanal ayarlarını yapma izni var"
|
||||
|
||||
msgid "Allowed to modify the access list"
|
||||
msgstr "Erişim listesini değiştirme izni var"
|
||||
|
||||
msgid "Allowed to read channel memos"
|
||||
msgstr "Kanal memolarını okuma izni var"
|
||||
|
||||
msgid "Allowed to set channel settings"
|
||||
msgstr "Kanal ayarlarını yapma izni var"
|
||||
|
||||
msgid "Allowed to unban themself"
|
||||
msgstr "Kendisini unban yapma izni var"
|
||||
|
||||
@@ -2953,6 +2952,14 @@ msgstr ""
|
||||
"erişim listesi boşsa\n"
|
||||
"kanal düşürülür."
|
||||
|
||||
#, c-format
|
||||
msgid "Changing your usermodes to %s"
|
||||
msgstr "Kullanıcı modlarınız %s olarak değiştiriliyor"
|
||||
|
||||
#, c-format
|
||||
msgid "Changing your vhost to %s"
|
||||
msgstr "Vhostunuz %s olarak değiştiriliyor"
|
||||
|
||||
msgid "Channel"
|
||||
msgstr "Kanal"
|
||||
|
||||
@@ -3668,7 +3675,7 @@ msgstr "%s için e-posta geçersiz."
|
||||
msgid "Email matched: %s (%s) to %s."
|
||||
msgstr "E-posta eşleşti: %s (%s) - %s."
|
||||
|
||||
msgid "Enable fantaisist commands"
|
||||
msgid "Enable fantasy commands"
|
||||
msgstr "Fantezi komutlarını etkinleştir"
|
||||
|
||||
msgid "Enable greet messages"
|
||||
@@ -3922,7 +3929,7 @@ msgstr ""
|
||||
"kullanıcıları atacaktır."
|
||||
|
||||
msgid "English"
|
||||
msgstr "İngilizce"
|
||||
msgstr "Türkçe"
|
||||
|
||||
#, c-format
|
||||
msgid "Entry message %i for %s deleted."
|
||||
@@ -4193,11 +4200,11 @@ msgid "Info about a loaded module"
|
||||
msgstr "Yüklü bir modül hakkında bilgi"
|
||||
|
||||
#, c-format
|
||||
msgid "Information for bot %s:"
|
||||
msgid "Information about bot %s:"
|
||||
msgstr "%s botu ile ilgili bilgiler:"
|
||||
|
||||
#, c-format
|
||||
msgid "Information for channel %s:"
|
||||
msgid "Information about channel %s:"
|
||||
msgstr "%s kanalı ile ilgili bilgiler:"
|
||||
|
||||
#, c-format
|
||||
@@ -4304,7 +4311,7 @@ msgid "LOGONNEWS {ADD|DEL|LIST} [text|num]"
|
||||
msgstr "LOGONNEWS {ADD|DEL|LIST} [metin|nu.]"
|
||||
|
||||
msgid "Language changed to English."
|
||||
msgstr "Dil İngilizce olarak değiştirildi."
|
||||
msgstr "Dil Türkçe olarak değiştirildi."
|
||||
|
||||
#, c-format
|
||||
msgid "Language for %s changed to %s."
|
||||
@@ -4778,7 +4785,7 @@ msgid ""
|
||||
"Maintains the bad words list 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 %s%s HELP KICK %s.\n"
|
||||
"type %s HELP KICK %s.\n"
|
||||
" \n"
|
||||
"The ADD command adds the given word to the\n"
|
||||
"bad words list. If SINGLE is specified, a kick will be\n"
|
||||
@@ -4793,7 +4800,7 @@ msgstr ""
|
||||
"Bir kanal için küfür listesini düzenler.\n"
|
||||
"küfür listesi, küfürlü konuşanları atma etkinleştirildiğinde\n"
|
||||
"hangi kelimelerin atılacağını belirler. Daha fazla bilgi\n"
|
||||
"için %s%s HELP KICK %s yazın.\n"
|
||||
"için %s HELP KICK %s yazın.\n"
|
||||
" \n"
|
||||
"ADD komutu belirtilen kelimeyi küfür\n"
|
||||
"listesine ekler. SINGLE belirtilirse, yalnızca kullanıcı\n"
|
||||
@@ -5402,8 +5409,8 @@ msgid "Persistent"
|
||||
msgstr "Kalıcı"
|
||||
|
||||
#, c-format
|
||||
msgid "Please confirm that you want to drop %s with %s%s DROP %s %s"
|
||||
msgstr "Lütfen %s rumuzunu droplamak isteğinizi %s%s DROP %s %s ile onaylayın"
|
||||
msgid "Please confirm that you want to drop %s with %s DROP %s %s"
|
||||
msgstr "Lütfen %s rumuzunu droplamak isteğinizi %s DROP %s %s ile onaylayın"
|
||||
|
||||
msgid "Please contact an Operator to get a vhost assigned to this nick."
|
||||
msgstr "Bu rumuza atanan bir vHost almak için lütfen bir operle iletişime geçin."
|
||||
@@ -5899,18 +5906,18 @@ msgstr "OPları koruma %s'de uygulandı."
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"See %s%s HELP %s for more information\n"
|
||||
"See %s HELP %s for more information\n"
|
||||
"about the access list."
|
||||
msgstr ""
|
||||
"Erişim listesi hakkında detaylı bilgi için %s%s HELP %s\n"
|
||||
"Erişim listesi hakkında detaylı bilgi için %s HELP %s\n"
|
||||
"komut çıktısına bakın."
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"See %s%s HELP %s for more information\n"
|
||||
"See %s HELP %s for more information\n"
|
||||
"about the flags system."
|
||||
msgstr ""
|
||||
"Bayrak sistemi hakkında detaylı bilgi için %s%s HELP %s\n"
|
||||
"Bayrak sistemi hakkında detaylı bilgi için %s HELP %s\n"
|
||||
"komut çıktısına bakın."
|
||||
|
||||
msgid "Send a memo to a nick or channel"
|
||||
@@ -6224,7 +6231,7 @@ msgid ""
|
||||
"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"
|
||||
"BADWORDS command. Type %s%s HELP BADWORDS for\n"
|
||||
"BADWORDS command. Type %s HELP BADWORDS for\n"
|
||||
"more information.\n"
|
||||
" \n"
|
||||
"ttb is the number of times a user can be kicked\n"
|
||||
@@ -6236,7 +6243,7 @@ msgstr ""
|
||||
"söyleyen kullanıcıları atmasını söyler.\n"
|
||||
"BADWORDS komutunu kullanarak kanalınıza küfür\n"
|
||||
"tanımlayabilirsiniz. Daha fazla bilgi için\n"
|
||||
"%s%s HELP BADWORDS yazın.\n"
|
||||
"%s HELP BADWORDS yazın.\n"
|
||||
" \n"
|
||||
"ttb, bir kullanıcının banlanmadan önce atılabileceği\n"
|
||||
"sayıdır. Ban sistemini aktif hale getirdikten sonra devre dışı\n"
|
||||
@@ -6461,7 +6468,7 @@ msgid ""
|
||||
" LIMIT Sets the maximum number of memos you can\n"
|
||||
" receive\n"
|
||||
" \n"
|
||||
"Type %s%s HELP %s option for more information\n"
|
||||
"Type %s HELP %s option for more information\n"
|
||||
"on a specific option."
|
||||
msgstr ""
|
||||
"Çeşitli memo seçeneklerini ayarlar. seçenek şunlardan biri olabilir:\n"
|
||||
@@ -6472,7 +6479,7 @@ msgstr ""
|
||||
" ayarlar\n"
|
||||
" \n"
|
||||
"Belirli bir seçenek hakkında daha fazla bilgi için\n"
|
||||
"%s%s HELP %s seçenek yazın."
|
||||
"%s HELP %s seçenek yazın."
|
||||
|
||||
msgid "Sets various nickname options. option can be one of:"
|
||||
msgstr "Çeşitli rumuz seçeneklerini ayarlar. seçenek şunlardan biri olabilir:"
|
||||
@@ -6527,8 +6534,8 @@ msgstr ""
|
||||
"modların otomatik olarak ayarlanamayacağını unutmayın."
|
||||
|
||||
#, c-format
|
||||
msgid "Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
|
||||
msgstr "%s ayarı bilinmiyor. Geçerli ayarların listesi için %s%s HELP LEVELS yazın."
|
||||
msgid "Setting %s not known. Type %s HELP LEVELS for a list of valid settings."
|
||||
msgstr "%s ayarı bilinmiyor. Geçerli ayarların listesi için %s HELP LEVELS yazın."
|
||||
|
||||
msgid "Setting for DEBUG must be ON, OFF, or a positive number."
|
||||
msgstr "DEBUG ayarı ON, OFF veya pozitif bir sayı olmalıdır."
|
||||
@@ -7438,10 +7445,10 @@ msgstr "%zu memo (%s kanalında) var."
|
||||
#, c-format
|
||||
msgid ""
|
||||
"There is a new memo on channel %s.\n"
|
||||
"Type %s%s READ %s %zu to read it."
|
||||
"Type %s READ %s %zu to read it."
|
||||
msgstr ""
|
||||
"%s kanalında yeni bir memo var. Okumak için\n"
|
||||
"%s%s READ %s %zu yazın."
|
||||
"%s READ %s %zu yazın."
|
||||
|
||||
#, c-format
|
||||
msgid "There is no bot assigned to %s anymore."
|
||||
@@ -7738,20 +7745,20 @@ msgstr "Bu rumuz askıya alındı."
|
||||
#, c-format
|
||||
msgid ""
|
||||
"This nickname is registered and protected. If it is your\n"
|
||||
"nick, type %s%s IDENTIFY password. Otherwise,\n"
|
||||
"nick, type %s IDENTIFY password. Otherwise,\n"
|
||||
"please choose a different nick."
|
||||
msgstr ""
|
||||
"Bu rumuz kayıtlı ve korumalıdır. Eğer sizin\n"
|
||||
"rumuzunuzsa, %s%s IDENTIFY şifreniz yazın. Aksi halde,\n"
|
||||
"rumuzunuzsa, %s IDENTIFY şifreniz yazın. Aksi halde,\n"
|
||||
"kendinize başka bir rumuz seçin."
|
||||
|
||||
#, c-format
|
||||
msgid "To delete, type: %s%s %s %d"
|
||||
msgstr "Silmek için şunu yazın: %s%s %s %d"
|
||||
msgid "To delete, type: %s %s %d"
|
||||
msgstr "Silmek için şunu yazın: %s %s %d"
|
||||
|
||||
#, c-format
|
||||
msgid "To delete, type: %s%s %s %s %d"
|
||||
msgstr "Silmek için şunu yazın: %s%s %s %s %d"
|
||||
msgid "To delete, type: %s %s %s %d"
|
||||
msgstr "Silmek için şunu yazın: %s%s %s %d"
|
||||
|
||||
msgid "To protect ops against bot kicks"
|
||||
msgstr "Opları bot atmalarına karşı korumak için"
|
||||
@@ -7906,46 +7913,46 @@ msgstr "Türü"
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Type %s%s HELP %s option for more information\n"
|
||||
"Type %s HELP %s option for more information\n"
|
||||
"on a specific option."
|
||||
msgstr ""
|
||||
"Belirli bir seçenek hakkında daha fazla bilgi için\n"
|
||||
"%s%s HELP %s seçenek yazın."
|
||||
"%s HELP %s seçenek yazın."
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Type %s%s HELP %s option for more information\n"
|
||||
"Type %s HELP %s option for more information\n"
|
||||
"on a specific option.\n"
|
||||
" \n"
|
||||
"Note: access to this command is controlled by the\n"
|
||||
"level SET."
|
||||
msgstr ""
|
||||
"Belirli bir seçenek hakkında daha fazla bilgi için\n"
|
||||
"%s%s HELP %s seçenek yazın. \n"
|
||||
"%s HELP %s seçenek yazın. \n"
|
||||
"Not: Bu komuta erişim SET seviyesi tarafından\n"
|
||||
"kontrol edilir."
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Type %s%s HELP %s option for more information\n"
|
||||
"Type %s HELP %s option for more information\n"
|
||||
"on a specific option. The options will be set on the given\n"
|
||||
"nickname."
|
||||
msgstr ""
|
||||
"Belirli bir seçenek hakkında daha fazla bilgi için\n"
|
||||
"%s%s HELP %s seçenek yazın. Seçenekler belirtilen\n"
|
||||
"%s HELP %s seçenek yazın. Seçenekler belirtilen\n"
|
||||
"rumuz'a göre ayarlanacaktır."
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Type %s%s HELP %s option for more information on a\n"
|
||||
"Type %s HELP %s option for more information on a\n"
|
||||
"particular option."
|
||||
msgstr ""
|
||||
"Belirli bir seçenek hakkında daha fazla bilgi için\n"
|
||||
"%s%s HELP %s seçenek yazın."
|
||||
"Özel bir seçenek hakkında daha fazla bilgi için\n"
|
||||
"%s HELP %s seçenek yazın."
|
||||
|
||||
#, c-format
|
||||
msgid "Type %s%s SET EMAIL email in order to set your email."
|
||||
msgstr "E-Postanızı ayarlamak için %s%s SET EMAIL e-posta yazın."
|
||||
msgid "Type %s SET EMAIL email in order to set your email."
|
||||
msgstr "E-Postanızı ayarlamak için %s SET EMAIL e-posta yazın."
|
||||
|
||||
msgid "Un-Load a module"
|
||||
msgstr "Bir modülün yüklemesini kaldır"
|
||||
@@ -7993,16 +8000,16 @@ msgid "Unknown command %s."
|
||||
msgstr "Bilinmeyen komut %s."
|
||||
|
||||
#, c-format
|
||||
msgid "Unknown command %s. \"%s%s HELP\" for help."
|
||||
msgstr "Bilinmeyen komut %s. Yardım için: \"%s%s HELP\"."
|
||||
msgid "Unknown command %s. \"%s HELP\" for help."
|
||||
msgstr "Bilinmeyen komut %s. Yardım için: \"%s HELP\"."
|
||||
|
||||
#, c-format
|
||||
msgid "Unknown command %s. Did you mean %s?"
|
||||
msgstr "Bilinmeyen komut %s. %s mi demek istediniz?"
|
||||
|
||||
#, c-format
|
||||
msgid "Unknown command %s. Did you mean %s? \"%s%s HELP\" for help."
|
||||
msgstr "Bilinmeyen komut %s. %s mi demek istediniz? Yardım için: \"%s%s HELP\"."
|
||||
msgid "Unknown command %s. Did you mean %s? \"%s HELP\" for help."
|
||||
msgstr "Bilinmeyen komut %s. %s mi demek istediniz? Yardım için: \"%s HELP\"."
|
||||
|
||||
#, c-format
|
||||
msgid "Unknown mode character %c ignored."
|
||||
@@ -8347,10 +8354,6 @@ msgstr "Bir kanalı, onun kendi erişim listesine ekleyemezsiniz."
|
||||
msgid "You can't logout %s, they are a Services Operator."
|
||||
msgstr "%s oturumunu kapatamazsınız, o bir Servis Operatörü."
|
||||
|
||||
#, c-format
|
||||
msgid "You cannot %s on this network."
|
||||
msgstr "Bu ağda %s yapamazsınız."
|
||||
|
||||
#, c-format
|
||||
msgid "You cannot set the %c flag."
|
||||
msgstr "%c bayrağını ayarlayamazsınız."
|
||||
@@ -8425,10 +8428,10 @@ msgstr "1 yeni memonuz var."
|
||||
#, c-format
|
||||
msgid ""
|
||||
"You have a new memo from %s.\n"
|
||||
"Type %s%s READ %zu to read it."
|
||||
"Type %s READ %zu to read it."
|
||||
msgstr ""
|
||||
"%s size yeni bir memo gönderdi.\n"
|
||||
"okumak için %s%s READ %zu yazın."
|
||||
"okumak için %s READ %zu yazın."
|
||||
|
||||
#, c-format
|
||||
msgid "You have been invited to %s by %s."
|
||||
@@ -8489,6 +8492,10 @@ msgstr "Diğer Servis Operatörlerinin e-postasını değiştiremezsiniz."
|
||||
msgid "You may not change the password of other Services Operators."
|
||||
msgstr "Diğer Servis Operatörlerinin şifresini değiştiremezsiniz."
|
||||
|
||||
#, c-format
|
||||
msgid "You may not drop %s as it is the display nick for the account."
|
||||
msgstr "Hesabın görüntülenen rumuzu olduğu için %s rumuzunu droplayamazsınız."
|
||||
|
||||
msgid "You may not drop other Services Operators' nicknames."
|
||||
msgstr "Diğer Servis Operatörlerinin rumuzlarını düşüremezsiniz."
|
||||
|
||||
@@ -8586,6 +8593,10 @@ msgstr "IRCd'niz SVSPART'ı desteklemiyor."
|
||||
msgid "Your IRCd does not support vidents. If this is incorrect please report this as a possible bug."
|
||||
msgstr "IRCd'niz vIdent'i desteklemiyor, eğer bu yanlışsa lütfen bunu olası bir hata olarak bildirin."
|
||||
|
||||
#, c-format
|
||||
msgid "Your SSL certificate fingerprint %s has been automatically added to your certificate list."
|
||||
msgstr "SSL sertifika parmak iziniz %s otomatik olarak sertifika listenize eklendi."
|
||||
|
||||
#, c-format
|
||||
msgid "Your account %s has been successfully created."
|
||||
msgstr "Hesabınız %s başarıyla oluşturuldu."
|
||||
|
||||
+1
-1
@@ -21,7 +21,6 @@ find ../ \
|
||||
\) \
|
||||
-exec \
|
||||
xgettext \
|
||||
--escape \
|
||||
--language=C++ \
|
||||
--sort-output \
|
||||
--default-domain=Anope \
|
||||
@@ -30,6 +29,7 @@ find ../ \
|
||||
--from-code=utf-8 \
|
||||
--keyword \
|
||||
--keyword=_ \
|
||||
--keyword=N_:1,2 \
|
||||
{} +
|
||||
|
||||
for f in *.po
|
||||
|
||||
@@ -153,11 +153,11 @@ public:
|
||||
"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%s \037command\037\002. For\n"
|
||||
"below; to use them, type \002%s \037command\037\002. For\n"
|
||||
"more information on a specific command, type\n"
|
||||
"\002%s%s %s \037command\037\002.\n"),
|
||||
BotServ->nick.c_str(), Config->StrictPrivmsg.c_str(), BotServ->nick.c_str(),
|
||||
Config->StrictPrivmsg.c_str(), BotServ->nick.c_str(), source.command.c_str());
|
||||
"\002%s %s \037command\037\002.\n"),
|
||||
BotServ->nick.c_str(), BotServ->GetQueryCommand().c_str(),
|
||||
BotServ->GetQueryCommand().c_str(), source.command.c_str());
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
@@ -430,7 +430,7 @@ public:
|
||||
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%s HELP KICK %s\002.\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"
|
||||
@@ -440,7 +440,7 @@ public:
|
||||
"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"), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
|
||||
" \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"
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
info[_("Real name")] = bi->realname;
|
||||
info[_("Created")] = Anope::strftime(bi->created, source.GetAccount());
|
||||
info[_("Options")] = bi->oper_only ? _("Private") : _("None");
|
||||
info[_("Used on")] = Anope::ToString(bi->GetChannelCount()) + " channel(s)";
|
||||
info[_("Used on")] = Anope::printf(Language::Translate(source.nc, N_("%u channel", "%u channels")), bi->GetChannelCount());
|
||||
|
||||
FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
|
||||
|
||||
|
||||
@@ -153,11 +153,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n"
|
||||
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."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
|
||||
"level SET."), source.service->GetQueryCommand().c_str(), this_name.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -308,12 +308,12 @@ public:
|
||||
"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%s HELP BADWORDS\002 for\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."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
|
||||
"the ban system once activated."), source.service->GetQueryCommand().c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,8 +58,8 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information on a\n"
|
||||
"particular option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
|
||||
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());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -262,9 +262,9 @@ public:
|
||||
"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%s \037command\037\002. For more information on a\n"
|
||||
"specific command, type \002%s%s HELP \037command\037\002.\n"),
|
||||
ChanServ->nick.c_str(), ChanServ->nick.c_str(), Config->StrictPrivmsg.c_str(), ChanServ->nick.c_str(), Config->StrictPrivmsg.c_str(), ChanServ->nick.c_str());
|
||||
"\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());
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -382,8 +382,11 @@ public:
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnPostInit() override
|
||||
void OnUplinkSync(Server* s) override
|
||||
{
|
||||
// We need to do this when the uplink is synced as we may not know if
|
||||
// the mode exists before then on some IRCds (e.g. InspIRCd).
|
||||
|
||||
if (!persist)
|
||||
return;
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ class CommandCSAccess final
|
||||
void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
Anope::string mask = params[2];
|
||||
Anope::string description = params.size() > 4 ? params[4] : "";
|
||||
Privilege *p = NULL;
|
||||
int level = ACCESS_INVALID;
|
||||
|
||||
@@ -172,7 +173,11 @@ class CommandCSAccess final
|
||||
{
|
||||
User *targ = User::Find(mask, true);
|
||||
if (targ != NULL)
|
||||
{
|
||||
mask = "*!*@" + targ->GetDisplayedHost();
|
||||
if (description.empty())
|
||||
description = targ->nick;
|
||||
}
|
||||
else
|
||||
{
|
||||
source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
|
||||
@@ -216,7 +221,7 @@ class CommandCSAccess final
|
||||
access->level = level;
|
||||
access->last_seen = 0;
|
||||
access->created = Anope::CurTime;
|
||||
access->description = params.size() > 4 ? params[4] : "";
|
||||
access->description = description;
|
||||
ci->AddAccess(access);
|
||||
|
||||
FOREACH_MOD(OnAccessAdd, (ci, source, access));
|
||||
@@ -625,8 +630,8 @@ public:
|
||||
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%s HELP LEVELS\002 for\n"
|
||||
"information."), cmd.c_str(), Config->StrictPrivmsg.c_str(), bi->nick.c_str());
|
||||
"\002%s\002 command; type \002%s HELP LEVELS\002 for\n"
|
||||
"information."), cmd.c_str(), bi->GetQueryCommand().c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -660,7 +665,10 @@ class CommandCSLevels final
|
||||
{
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(what);
|
||||
if (p == NULL)
|
||||
source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS\002 for a list of valid settings."), what.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
|
||||
{
|
||||
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());
|
||||
}
|
||||
else
|
||||
{
|
||||
bool override = !source.AccessFor(ci).HasPriv("FOUNDER");
|
||||
@@ -701,7 +709,8 @@ class CommandCSLevels final
|
||||
return;
|
||||
}
|
||||
|
||||
source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS\002 for a list of valid settings."), what.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
|
||||
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());
|
||||
}
|
||||
|
||||
static void DoList(CommandSource &source, ChannelInfo *ci)
|
||||
|
||||
@@ -58,8 +58,8 @@ public:
|
||||
*code = Anope::Random(15);
|
||||
}
|
||||
|
||||
source.Reply(CONFIRM_DROP, ci->name.c_str(), Config->StrictPrivmsg.c_str(),
|
||||
source.service->nick.c_str(), ci->name.c_str(), code->c_str());
|
||||
source.Reply(CONFIRM_DROP, ci->name.c_str(), source.service->GetQueryCommand().c_str(),
|
||||
ci->name.c_str(), code->c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ FlagsAccessProvider *FlagsAccessProvider::ap;
|
||||
class CommandCSFlags final
|
||||
: public Command
|
||||
{
|
||||
void DoModify(CommandSource &source, ChannelInfo *ci, Anope::string mask, const Anope::string &flags, const Anope::string &description)
|
||||
void DoModify(CommandSource &source, ChannelInfo *ci, Anope::string mask, const Anope::string &flags, Anope::string description)
|
||||
{
|
||||
if (flags.empty())
|
||||
{
|
||||
@@ -131,7 +131,11 @@ class CommandCSFlags final
|
||||
{
|
||||
User *targ = User::Find(mask, true);
|
||||
if (targ != NULL)
|
||||
{
|
||||
mask = "*!*@" + targ->GetDisplayedHost();
|
||||
if (description.empty())
|
||||
description = targ->nick;
|
||||
}
|
||||
else
|
||||
{
|
||||
source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
|
||||
|
||||
@@ -100,9 +100,9 @@ public:
|
||||
Anope::string cmd;
|
||||
if (Command::FindCommandFromService("chanserv/access", bi, cmd))
|
||||
source.Reply(_(" \n"
|
||||
"See the \002%s\002 command (\002%s%s HELP ACCESS\002) for\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(), Config->StrictPrivmsg.c_str(), bi->nick.c_str());
|
||||
"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"
|
||||
"first registered your nickname."));
|
||||
|
||||
@@ -59,8 +59,8 @@ public:
|
||||
c->OnServHelp(source);
|
||||
}
|
||||
}
|
||||
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information on a\n"
|
||||
"particular option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
|
||||
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());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -513,12 +513,13 @@ public:
|
||||
/* Set the perm mode */
|
||||
if (cm)
|
||||
{
|
||||
if (ci->c && !ci->c->HasMode("PERM"))
|
||||
ci->c->SetMode(NULL, cm);
|
||||
/* Add it to the channels mlock */
|
||||
ModeLocks *ml = ci->Require<ModeLocks>("modelocks");
|
||||
if (ml)
|
||||
ml->SetMLock(cm, true, "", source.GetNick());
|
||||
|
||||
if (ci->c && !ci->c->HasMode("PERM"))
|
||||
ci->c->SetMode(NULL, cm);
|
||||
}
|
||||
/* No botserv bot, no channel mode, give them ChanServ.
|
||||
* Yes, this works fine with no BotServ.
|
||||
@@ -556,12 +557,13 @@ public:
|
||||
/* Unset perm mode */
|
||||
if (cm)
|
||||
{
|
||||
if (ci->c && ci->c->HasMode("PERM"))
|
||||
ci->c->RemoveMode(NULL, cm);
|
||||
/* Remove from mlock */
|
||||
ModeLocks *ml = ci->GetExt<ModeLocks>("modelocks");
|
||||
if (ml)
|
||||
ml->RemoveMLock(cm, true);
|
||||
|
||||
if (ci->c && ci->c->HasMode("PERM"))
|
||||
ci->c->RemoveMode(NULL, cm);
|
||||
}
|
||||
/* No channel mode, no BotServ, but using ChanServ as the botserv bot
|
||||
* which was assigned when persist was set on
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
static Module *me;
|
||||
|
||||
static Anope::map<Anope::string> descriptions;
|
||||
static Anope::map<uint16_t> numerics;
|
||||
|
||||
struct CSMiscData;
|
||||
static Anope::map<ExtensibleItem<CSMiscData> *> items;
|
||||
@@ -189,6 +190,7 @@ public:
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
{
|
||||
descriptions.clear();
|
||||
numerics.clear();
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("command"); ++i)
|
||||
{
|
||||
@@ -204,9 +206,31 @@ public:
|
||||
continue;
|
||||
|
||||
descriptions[cname] = desc;
|
||||
|
||||
auto numeric = block->Get<unsigned>("misc_numeric");
|
||||
if (numeric >= 1 && numeric <= 999)
|
||||
numerics["cs_set_misc:" + GetAttribute(cname)] = numeric;
|
||||
}
|
||||
}
|
||||
|
||||
void OnJoinChannel(User *user, Channel *c) override
|
||||
{
|
||||
if (!c->ci || !user->server->IsSynced() || numerics.empty())
|
||||
return;
|
||||
|
||||
for (const auto &[name, ext] : items)
|
||||
{
|
||||
auto *data = ext->Get(c->ci);
|
||||
if (!data)
|
||||
continue;
|
||||
|
||||
auto numeric = numerics.find(name);
|
||||
if (numeric != numerics.end())
|
||||
IRCD->SendNumeric(numeric->second, user->GetUID(), c->ci->name, data->data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool) override
|
||||
{
|
||||
for (const auto &[_, e] : items)
|
||||
|
||||
@@ -11,57 +11,47 @@
|
||||
class StatusUpdate final
|
||||
: public Module
|
||||
{
|
||||
public:
|
||||
StatusUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
|
||||
private:
|
||||
void OnAccessChange(ChannelInfo *ci, ChanAccess *access, bool adding)
|
||||
{
|
||||
if (!ci->c)
|
||||
return;
|
||||
|
||||
for (const auto &[_, uc] : ci->c->users)
|
||||
{
|
||||
auto *user = uc->user;
|
||||
|
||||
ChannelInfo *next;
|
||||
if (user->server != Me && access->Matches(user, user->Account(), next))
|
||||
{
|
||||
auto ag = ci->AccessFor(user);
|
||||
|
||||
for (auto *cms : ModeManager::GetStatusChannelModesByRank())
|
||||
{
|
||||
if (!ag.HasPriv("AUTO" + cms->name))
|
||||
ci->c->RemoveMode(NULL, cms, user->GetUID());
|
||||
}
|
||||
|
||||
if (adding)
|
||||
ci->c->SetCorrectModes(user, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
StatusUpdate(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
{
|
||||
}
|
||||
|
||||
void OnAccessAdd(ChannelInfo *ci, CommandSource &, ChanAccess *access) override
|
||||
{
|
||||
if (ci->c)
|
||||
{
|
||||
for (const auto &[_, uc] : ci->c->users)
|
||||
{
|
||||
User *user = uc->user;
|
||||
|
||||
ChannelInfo *next;
|
||||
if (user->server != Me && access->Matches(user, user->Account(), next))
|
||||
{
|
||||
AccessGroup ag = ci->AccessFor(user);
|
||||
|
||||
for (auto *cms : ModeManager::GetStatusChannelModesByRank())
|
||||
{
|
||||
if (!ag.HasPriv("AUTO" + cms->name))
|
||||
ci->c->RemoveMode(NULL, cms, user->GetUID());
|
||||
}
|
||||
ci->c->SetCorrectModes(user, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
OnAccessChange(ci, access, true);
|
||||
}
|
||||
|
||||
void OnAccessDel(ChannelInfo *ci, CommandSource &, ChanAccess *access) override
|
||||
{
|
||||
if (ci->c)
|
||||
{
|
||||
for (const auto &[_, uc] : ci->c->users)
|
||||
{
|
||||
User *user = uc->user;
|
||||
|
||||
ChannelInfo *next;
|
||||
if (user->server != Me && access->Matches(user, user->Account(), next))
|
||||
{
|
||||
AccessGroup ag = ci->AccessFor(user);
|
||||
|
||||
for (auto *cms : ModeManager::GetStatusChannelModesByRank())
|
||||
{
|
||||
if (!ag.HasPriv("AUTO" + cms->name))
|
||||
ci->c->RemoveMode(NULL, cms, user->GetUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
OnAccessChange(ci, access, false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -179,7 +179,11 @@ private:
|
||||
{
|
||||
User *targ = User::Find(mask, true);
|
||||
if (targ != NULL)
|
||||
{
|
||||
mask = "*!*@" + targ->GetDisplayedHost();
|
||||
if (description.empty())
|
||||
description = targ->nick;
|
||||
}
|
||||
else
|
||||
{
|
||||
source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
|
||||
@@ -590,11 +594,11 @@ public:
|
||||
source.Reply(_("Alternative methods of modifying channel access lists are\n"
|
||||
"available."));
|
||||
if (!access_cmd.empty())
|
||||
source.Reply(_("See \002%s%s HELP %s\002 for more information\n"
|
||||
"about the access list."), Config->StrictPrivmsg.c_str(), access_bi->nick.c_str(), access_cmd.c_str());
|
||||
source.Reply(_("See \002%s HELP %s\002 for more information\n"
|
||||
"about the access list."), access_bi->GetQueryCommand().c_str(), access_cmd.c_str());
|
||||
if (!flags_cmd.empty())
|
||||
source.Reply(_("See \002%s%s HELP %s\002 for more information\n"
|
||||
"about the flags system."), Config->StrictPrivmsg.c_str(), flags_bi->nick.c_str(), flags_cmd.c_str());
|
||||
source.Reply(_("See \002%s HELP %s\002 for more information\n"
|
||||
"about the flags system."), flags_bi->GetQueryCommand().c_str(), flags_cmd.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+44
-44
@@ -212,7 +212,7 @@ class MChanstats final
|
||||
|
||||
Anope::string GetDisplay(User *u)
|
||||
{
|
||||
if (u && u->Account() && ns_stats.HasExt(u->Account()))
|
||||
if (u && u->IsIdentified() && ns_stats.HasExt(u->Account()))
|
||||
return u->Account()->display;
|
||||
else
|
||||
return "";
|
||||
@@ -278,45 +278,45 @@ class MChanstats final
|
||||
if (!this->HasTable(prefix +"chanstats"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "chanstats` ("
|
||||
"`id` int(11) NOT NULL AUTO_INCREMENT,"
|
||||
"`id` int NOT NULL AUTO_INCREMENT,"
|
||||
"`chan` varchar(64) NOT NULL DEFAULT '',"
|
||||
"`nick` varchar(64) NOT NULL DEFAULT '',"
|
||||
"`type` ENUM('total', 'monthly', 'weekly', 'daily') NOT NULL,"
|
||||
"`letters` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`words` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`line` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`actions` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`smileys_happy` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`smileys_sad` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`smileys_other` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`kicks` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`kicked` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`modes` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`topics` int(10) unsigned NOT NULL DEFAULT '0',"
|
||||
"`time0` int(10) unsigned NOT NULL default '0',"
|
||||
"`time1` int(10) unsigned NOT NULL default '0',"
|
||||
"`time2` int(10) unsigned NOT NULL default '0',"
|
||||
"`time3` int(10) unsigned NOT NULL default '0',"
|
||||
"`time4` int(10) unsigned NOT NULL default '0',"
|
||||
"`time5` int(10) unsigned NOT NULL default '0',"
|
||||
"`time6` int(10) unsigned NOT NULL default '0',"
|
||||
"`time7` int(10) unsigned NOT NULL default '0',"
|
||||
"`time8` int(10) unsigned NOT NULL default '0',"
|
||||
"`time9` int(10) unsigned NOT NULL default '0',"
|
||||
"`time10` int(10) unsigned NOT NULL default '0',"
|
||||
"`time11` int(10) unsigned NOT NULL default '0',"
|
||||
"`time12` int(10) unsigned NOT NULL default '0',"
|
||||
"`time13` int(10) unsigned NOT NULL default '0',"
|
||||
"`time14` int(10) unsigned NOT NULL default '0',"
|
||||
"`time15` int(10) unsigned NOT NULL default '0',"
|
||||
"`time16` int(10) unsigned NOT NULL default '0',"
|
||||
"`time17` int(10) unsigned NOT NULL default '0',"
|
||||
"`time18` int(10) unsigned NOT NULL default '0',"
|
||||
"`time19` int(10) unsigned NOT NULL default '0',"
|
||||
"`time20` int(10) unsigned NOT NULL default '0',"
|
||||
"`time21` int(10) unsigned NOT NULL default '0',"
|
||||
"`time22` int(10) unsigned NOT NULL default '0',"
|
||||
"`time23` int(10) unsigned NOT NULL default '0',"
|
||||
"`letters` bigint unsigned NOT NULL DEFAULT '0',"
|
||||
"`words` bigint unsigned NOT NULL DEFAULT '0',"
|
||||
"`line` int unsigned NOT NULL DEFAULT '0',"
|
||||
"`actions` int unsigned NOT NULL DEFAULT '0',"
|
||||
"`smileys_happy` int unsigned NOT NULL DEFAULT '0',"
|
||||
"`smileys_sad` int unsigned NOT NULL DEFAULT '0',"
|
||||
"`smileys_other` int unsigned NOT NULL DEFAULT '0',"
|
||||
"`kicks` int unsigned NOT NULL DEFAULT '0',"
|
||||
"`kicked` int unsigned NOT NULL DEFAULT '0',"
|
||||
"`modes` int unsigned NOT NULL DEFAULT '0',"
|
||||
"`topics` int unsigned NOT NULL DEFAULT '0',"
|
||||
"`time0` int unsigned NOT NULL default '0',"
|
||||
"`time1` int unsigned NOT NULL default '0',"
|
||||
"`time2` int unsigned NOT NULL default '0',"
|
||||
"`time3` int unsigned NOT NULL default '0',"
|
||||
"`time4` int unsigned NOT NULL default '0',"
|
||||
"`time5` int unsigned NOT NULL default '0',"
|
||||
"`time6` int unsigned NOT NULL default '0',"
|
||||
"`time7` int unsigned NOT NULL default '0',"
|
||||
"`time8` int unsigned NOT NULL default '0',"
|
||||
"`time9` int unsigned NOT NULL default '0',"
|
||||
"`time10` int unsigned NOT NULL default '0',"
|
||||
"`time11` int unsigned NOT NULL default '0',"
|
||||
"`time12` int unsigned NOT NULL default '0',"
|
||||
"`time13` int unsigned NOT NULL default '0',"
|
||||
"`time14` int unsigned NOT NULL default '0',"
|
||||
"`time15` int unsigned NOT NULL default '0',"
|
||||
"`time16` int unsigned NOT NULL default '0',"
|
||||
"`time17` int unsigned NOT NULL default '0',"
|
||||
"`time18` int unsigned NOT NULL default '0',"
|
||||
"`time19` int unsigned NOT NULL default '0',"
|
||||
"`time20` int unsigned NOT NULL default '0',"
|
||||
"`time21` int unsigned NOT NULL default '0',"
|
||||
"`time22` int unsigned NOT NULL default '0',"
|
||||
"`time23` int unsigned NOT NULL default '0',"
|
||||
"PRIMARY KEY (`id`),"
|
||||
"UNIQUE KEY `chan` (`chan`,`nick`,`type`),"
|
||||
"KEY `nick` (`nick`),"
|
||||
@@ -332,9 +332,9 @@ class MChanstats final
|
||||
this->RunQuery(query);
|
||||
}
|
||||
query = "CREATE PROCEDURE `" + prefix + "chanstats_proc_update`"
|
||||
"(chan_ VARCHAR(255), nick_ VARCHAR(255), line_ INT(10), letters_ INT(10),"
|
||||
"words_ INT(10), actions_ INT(10), sm_h_ INT(10), sm_s_ INT(10), sm_o_ INT(10),"
|
||||
"kicks_ INT(10), kicked_ INT(10), modes_ INT(10), topics_ INT(10))"
|
||||
"(chan_ VARCHAR(255), nick_ VARCHAR(255), line_ int, letters_ int,"
|
||||
"words_ int, actions_ int, sm_h_ int, sm_s_ int, sm_o_ int,"
|
||||
"kicks_ int, kicked_ int, modes_ int, topics_ int)"
|
||||
"BEGIN "
|
||||
"DECLARE time_ VARCHAR(20);"
|
||||
"SET time_ = CONCAT('time', hour(now()));"
|
||||
@@ -368,7 +368,7 @@ class MChanstats final
|
||||
query = "CREATE PROCEDURE `" + prefix + "chanstats_proc_chgdisplay`"
|
||||
"(old_nick varchar(255), new_nick varchar(255))"
|
||||
"BEGIN "
|
||||
"DECLARE res_count int(10) unsigned;"
|
||||
"DECLARE res_count int unsigned;"
|
||||
"SELECT COUNT(nick) INTO res_count FROM `" + prefix + "chanstats` WHERE nick = new_nick;"
|
||||
"IF res_count = 0 THEN "
|
||||
"UPDATE `" + prefix + "chanstats` SET `nick` = new_nick WHERE `nick` = old_nick;"
|
||||
@@ -381,7 +381,7 @@ class MChanstats final
|
||||
"smileys_sad_, smileys_other_, kicks_, kicked_, modes_, topics_,"
|
||||
"time0_, time1_, time2_, time3_, time4_, time5_, time6_, time7_, time8_, time9_,"
|
||||
"time10_, time11_, time12_, time13_, time14_, time15_, time16_, time17_, time18_,"
|
||||
"time19_, time20_, time21_, time22_, time23_ INT(10) unsigned;"
|
||||
"time19_, time20_, time21_, time22_, time23_ int unsigned;"
|
||||
"DECLARE stats_cursor CURSOR FOR "
|
||||
"SELECT chan, type, letters, words, line, actions, smileys_happy,"
|
||||
"smileys_sad, smileys_other, kicks, kicked, modes, topics, time0, time1,"
|
||||
@@ -532,7 +532,7 @@ public:
|
||||
|
||||
void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) override
|
||||
{
|
||||
if (!source || !source->Account() || !c->ci || !cs_stats.HasExt(c->ci))
|
||||
if (!source || !source->IsIdentified() || !c->ci || !cs_stats.HasExt(c->ci))
|
||||
return;
|
||||
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);";
|
||||
query.SetValue("channel", c->name);
|
||||
@@ -555,7 +555,7 @@ public:
|
||||
private:
|
||||
void OnModeChange(Channel *c, User *u)
|
||||
{
|
||||
if (!u || !u->Account() || !c->ci || !cs_stats.HasExt(c->ci))
|
||||
if (!u || !u->IsIdentified() || !c->ci || !cs_stats.HasExt(c->ci))
|
||||
return;
|
||||
|
||||
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);";
|
||||
|
||||
@@ -72,6 +72,11 @@ class DBSQL final
|
||||
bool loaded = false;
|
||||
bool imported = false;
|
||||
|
||||
Anope::string GetTableName(Serialize::Type *s_type)
|
||||
{
|
||||
return this->prefix + s_type->GetName();
|
||||
}
|
||||
|
||||
void RunBackground(const Query &q, Interface *iface = NULL)
|
||||
{
|
||||
if (!this->sql)
|
||||
@@ -124,8 +129,8 @@ public:
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
std::vector<Query> create = this->sql->CreateTable(this->prefix + s_type->GetName(), data);
|
||||
Query insert = this->sql->BuildInsert(this->prefix + s_type->GetName(), obj->id, data);
|
||||
auto create = this->sql->CreateTable(GetTableName(s_type), data);
|
||||
auto insert = this->sql->BuildInsert(GetTableName(s_type), obj->id, data);
|
||||
|
||||
if (this->imported)
|
||||
{
|
||||
@@ -161,6 +166,14 @@ public:
|
||||
this->import = block->Get<bool>("import");
|
||||
}
|
||||
|
||||
void OnPostInit() override
|
||||
{
|
||||
// If we are importing from flatfile we need to force a socket engine
|
||||
// flush to ensure it actually gets written to the database before we
|
||||
// connect to the uplink.
|
||||
SocketEngine::Process();
|
||||
}
|
||||
|
||||
void OnShutdown() override
|
||||
{
|
||||
this->shutting_down = true;
|
||||
@@ -209,7 +222,7 @@ public:
|
||||
return;
|
||||
Serialize::Type *s_type = obj->GetSerializableType();
|
||||
if (s_type && obj->id > 0)
|
||||
this->RunBackground("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + Anope::ToString(obj->id));
|
||||
this->RunBackground("DELETE FROM `" + GetTableName(s_type) + "` WHERE `id` = " + Anope::ToString(obj->id));
|
||||
this->updated_items.erase(obj);
|
||||
}
|
||||
|
||||
@@ -229,7 +242,7 @@ public:
|
||||
if (!this->loading_databases && !this->loaded)
|
||||
return;
|
||||
|
||||
Query query("SELECT * FROM `" + this->prefix + sb->GetName() + "`");
|
||||
Query query("SELECT * FROM `" + GetTableName(sb) + "`");
|
||||
Result res = this->sql->RunQuery(query);
|
||||
|
||||
for (int j = 0; j < res.Rows(); ++j)
|
||||
|
||||
@@ -53,13 +53,12 @@ private:
|
||||
return init && SQL;
|
||||
}
|
||||
|
||||
void RunQuery(const Query &query)
|
||||
Anope::string GetTableName(Serialize::Type *s_type)
|
||||
{
|
||||
/* Can this be threaded? */
|
||||
this->RunQueryResult(query);
|
||||
return this->prefix + s_type->GetName();
|
||||
}
|
||||
|
||||
Result RunQueryResult(const Query &query)
|
||||
Result RunQuery(const Query &query)
|
||||
{
|
||||
if (this->CheckSQL())
|
||||
{
|
||||
@@ -106,11 +105,11 @@ public:
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
std::vector<Query> create = this->SQL->CreateTable(this->prefix + s_type->GetName(), data);
|
||||
auto create = this->SQL->CreateTable(GetTableName(s_type), data);
|
||||
for (const auto &query : create)
|
||||
this->RunQueryResult(query);
|
||||
this->RunQuery(query);
|
||||
|
||||
Result res = this->RunQueryResult(this->SQL->BuildInsert(this->prefix + s_type->GetName(), obj->id, data));
|
||||
auto res = this->RunQuery(this->SQL->BuildInsert(GetTableName(s_type), obj->id, data));
|
||||
if (res.GetID() && obj->id != res.GetID())
|
||||
{
|
||||
/* In this case obj is new, so place it into the object map */
|
||||
@@ -163,7 +162,7 @@ public:
|
||||
if (s_type)
|
||||
{
|
||||
if (obj->id > 0)
|
||||
this->RunQuery("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + Anope::ToString(obj->id));
|
||||
this->RunQuery("DELETE FROM `" + GetTableName(s_type) + "` WHERE `id` = " + Anope::ToString(obj->id));
|
||||
s_type->objects.erase(obj->id);
|
||||
}
|
||||
this->updated_items.erase(obj);
|
||||
@@ -174,11 +173,11 @@ public:
|
||||
if (!this->CheckInit() || obj->GetTimestamp() == Anope::CurTime)
|
||||
return;
|
||||
|
||||
Query query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` >= " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
|
||||
Query query("SELECT * FROM `" + GetTableName(obj) + "` WHERE (`timestamp` >= " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
|
||||
|
||||
obj->UpdateTimestamp();
|
||||
|
||||
Result res = this->RunQueryResult(query);
|
||||
Result res = this->RunQuery(query);
|
||||
|
||||
bool clear_null = false;
|
||||
for (int i = 0; i < res.Rows(); ++i)
|
||||
@@ -236,7 +235,7 @@ public:
|
||||
else
|
||||
{
|
||||
if (!s)
|
||||
this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + Anope::ToString(id));
|
||||
this->RunQuery("UPDATE `" + GetTableName(obj) + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + Anope::ToString(id));
|
||||
else
|
||||
delete s;
|
||||
}
|
||||
@@ -245,7 +244,7 @@ public:
|
||||
|
||||
if (clear_null)
|
||||
{
|
||||
query = "DELETE FROM `" + this->prefix + obj->GetName() + "` WHERE `timestamp` IS NULL";
|
||||
query = "DELETE FROM `" + GetTableName(obj) + "` WHERE `timestamp` IS NULL";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ public:
|
||||
if (!blacklist.replies.empty() && !reply)
|
||||
return;
|
||||
|
||||
if (reply && reply->allow_account && user->Account())
|
||||
if (reply && reply->allow_account && user->IsIdentified())
|
||||
return;
|
||||
|
||||
Anope::string reason = this->blacklist.reason, addr = user->ip.addr();
|
||||
|
||||
@@ -139,8 +139,19 @@ public:
|
||||
, argon2dprovider(this, Argon2_d)
|
||||
, argon2iprovider(this, Argon2_i)
|
||||
, argon2idprovider(this, Argon2_id)
|
||||
|
||||
{
|
||||
argon2dprovider.Check({
|
||||
{ "$argon2d$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$fNS8JrvE8EqKwQ", "" },
|
||||
{ "$argon2d$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$hTvpprMF0TwszQ", "The quick brown fox jumps over the lazy dog" },
|
||||
});
|
||||
argon2iprovider.Check({
|
||||
{ "$argon2i$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$neE6hYxRp4TCJA", "" },
|
||||
{ "$argon2i$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$/JAt4FdP1MFD+A", "The quick brown fox jumps over the lazy dog" },
|
||||
});
|
||||
argon2idprovider.Check({
|
||||
{ "$argon2id$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$wuNeHixFDS6Tkg", "" },
|
||||
{ "$argon2id$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$Po8RcmxZ7vHmdg", "The quick brown fox jumps over the lazy dog" },
|
||||
});
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
|
||||
+109
-16
@@ -159,28 +159,52 @@ public:
|
||||
|
||||
Anope::string FromUnixtime(time_t) override;
|
||||
|
||||
Anope::string GetColumnType(Serialize::DataType dt)
|
||||
const char* GetColumnDefault(Serialize::DataType dt)
|
||||
{
|
||||
switch (dt)
|
||||
{
|
||||
case Serialize::DataType::BOOL:
|
||||
return "TINYINT NOT NULL";
|
||||
|
||||
case Serialize::DataType::FLOAT:
|
||||
return "DOUBLE PRECISION NOT NULL";
|
||||
|
||||
case Serialize::DataType::INT:
|
||||
return "BIGINT NOT NULL";
|
||||
case Serialize::DataType::UINT:
|
||||
return "0";
|
||||
case Serialize::DataType::FLOAT:
|
||||
return "0.0";
|
||||
case Serialize::DataType::TEXT:
|
||||
return "NULL";
|
||||
}
|
||||
return "NULL"; // Should never be reached
|
||||
}
|
||||
|
||||
bool GetColumnNull(Serialize::DataType dt)
|
||||
{
|
||||
return dt == Serialize::DataType::TEXT;
|
||||
}
|
||||
|
||||
const char* GetColumnType(Serialize::DataType dt)
|
||||
{
|
||||
switch (dt)
|
||||
{
|
||||
case Serialize::DataType::BOOL:
|
||||
return "TINYINT";
|
||||
case Serialize::DataType::FLOAT:
|
||||
return "DOUBLE";
|
||||
case Serialize::DataType::INT:
|
||||
return "BIGINT";
|
||||
case Serialize::DataType::TEXT:
|
||||
return "TEXT";
|
||||
|
||||
case Serialize::DataType::UINT:
|
||||
return "BIGINT UNSIGNED NOT NULL";
|
||||
return "BIGINT UNSIGNED";
|
||||
}
|
||||
|
||||
return "TEXT"; // Should never be reached
|
||||
}
|
||||
|
||||
Anope::string GetColumn(Serialize::DataType dt)
|
||||
{
|
||||
return Anope::printf("%s %s DEFAULT %s",
|
||||
GetColumnType(dt),
|
||||
GetColumnNull(dt) ? "NULL" : "NOT NULL",
|
||||
GetColumnDefault(dt));
|
||||
}
|
||||
};
|
||||
|
||||
/** The SQL thread used to execute queries
|
||||
@@ -424,10 +448,79 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
|
||||
Result columns = this->RunQuery("SHOW COLUMNS FROM `" + table + "`");
|
||||
for (int i = 0; i < columns.Rows(); ++i)
|
||||
{
|
||||
const Anope::string &column = columns.Get(i, "Field");
|
||||
|
||||
const auto column = columns.Get(i, "Field");
|
||||
Log(LOG_DEBUG) << "mysql: Column #" << i << " for " << table << ": " << column;
|
||||
|
||||
if (column == "id" || column == "timestamp")
|
||||
continue; // These columns are special and aren't part of the data.
|
||||
|
||||
known_cols.insert(column);
|
||||
if (data.data.count(column) == 0)
|
||||
{
|
||||
Log(LOG_DEBUG) << "mysql: Column has been removed from the data set: " << column;
|
||||
continue;
|
||||
}
|
||||
|
||||
// We know the column exists but is the type correct?
|
||||
auto update = false;
|
||||
const auto stype = data.GetType(column);
|
||||
|
||||
auto coldef = columns.Get(i, "Default");
|
||||
if (coldef.empty())
|
||||
coldef = "NULL";
|
||||
|
||||
const auto *newcoldef = GetColumnDefault(stype);
|
||||
if (!coldef.equals_ci(newcoldef))
|
||||
{
|
||||
Log(LOG_DEBUG) << "mysql: Updating the default of " << column << " from " << coldef << " to " << newcoldef;
|
||||
update = true;
|
||||
}
|
||||
|
||||
const auto colnull = columns.Get(i, "Null");
|
||||
const auto newcolnull = GetColumnNull(stype) ? "YES" : "NO";
|
||||
if (!colnull.equals_ci(newcolnull))
|
||||
{
|
||||
Log(LOG_DEBUG) << "mysql: Updating the nullability of " << column << " from " << colnull << " to " << newcolnull;
|
||||
update = true;
|
||||
}
|
||||
|
||||
const auto coltype = columns.Get(i, "Type");
|
||||
const auto *newcoltype = GetColumnType(stype);
|
||||
if (!coltype.equals_ci(newcoltype))
|
||||
{
|
||||
Log(LOG_DEBUG) << "mysql: Updating the type of " << column << " from " << coltype << " to " << newcoltype;
|
||||
update = true;
|
||||
}
|
||||
|
||||
if (update)
|
||||
{
|
||||
// We can't just use MODIFY COLUMN here because the value may not
|
||||
// be valid and we may need to replace with the default.
|
||||
auto res = this->RunQuery(Anope::printf("ALTER TABLE `%s` ADD COLUMN `%s_new` %s; ",
|
||||
table.c_str(), column.c_str(), GetColumn(stype).c_str()));
|
||||
|
||||
if (res)
|
||||
{
|
||||
res = this->RunQuery(Anope::printf("UPDATE IGNORE `%s` SET `%s_new` = %s; ",
|
||||
table.c_str(), column.c_str(), column.c_str()));
|
||||
}
|
||||
|
||||
if (res)
|
||||
{
|
||||
res = this->RunQuery(Anope::printf("ALTER TABLE `%s` DROP COLUMN `%s`; ",
|
||||
table.c_str(), column.c_str()));
|
||||
}
|
||||
|
||||
if (res)
|
||||
{
|
||||
res = this->RunQuery(Anope::printf("ALTER TABLE `%s` RENAME COLUMN `%s_new` TO `%s`; ",
|
||||
table.c_str(), column.c_str(), column.c_str()));
|
||||
}
|
||||
|
||||
if (!res)
|
||||
Log(LOG_DEBUG) << "Failed to migrate the " << column << " column: " << res.GetError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,7 +532,7 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
|
||||
{
|
||||
known_cols.insert(column);
|
||||
|
||||
query_text += ", `" + column + "` " + GetColumnType(data.GetType(column));
|
||||
query_text += ", `" + column + "` " + GetColumn(data.GetType(column));
|
||||
}
|
||||
query_text += ", PRIMARY KEY (`id`), KEY `timestamp_idx` (`timestamp`)) ROW_FORMAT=DYNAMIC";
|
||||
queries.push_back(query_text);
|
||||
@@ -453,7 +546,7 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
|
||||
|
||||
known_cols.insert(column);
|
||||
|
||||
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + column + "` " + GetColumnType(data.GetType(column));
|
||||
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + column + "` " + GetColumn(data.GetType(column));
|
||||
|
||||
queries.push_back(query_text);
|
||||
}
|
||||
@@ -467,7 +560,7 @@ Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Dat
|
||||
/* Empty columns not present in the data set */
|
||||
for (const auto &known_col : this->active_schema[table])
|
||||
{
|
||||
if (known_col != "id" && known_col != "timestamp" && data.data.count(known_col) == 0)
|
||||
if (data.data.count(known_col) == 0)
|
||||
data[known_col] << "";
|
||||
}
|
||||
|
||||
@@ -498,7 +591,7 @@ Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Dat
|
||||
case Serialize::DataType::UINT:
|
||||
{
|
||||
if (buf.empty())
|
||||
buf = "0";
|
||||
buf = "DEFAULT";
|
||||
escape = false;
|
||||
break;
|
||||
}
|
||||
@@ -507,7 +600,7 @@ Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Dat
|
||||
{
|
||||
if (buf.empty())
|
||||
{
|
||||
buf = "NULL";
|
||||
buf = "DEFAULT";
|
||||
escape = false;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -51,14 +51,14 @@ public:
|
||||
* @param sz How much to read
|
||||
* @return Number of bytes received
|
||||
*/
|
||||
int Recv(Socket *s, char *buf, size_t sz) override;
|
||||
ssize_t Recv(Socket *s, char *buf, size_t sz) override;
|
||||
|
||||
/** Write something to the socket
|
||||
* @param s The socket
|
||||
* @param buf The data to write
|
||||
* @param size The length of the data
|
||||
*/
|
||||
int Send(Socket *s, const char *buf, size_t sz) override;
|
||||
ssize_t Send(Socket *s, const char *buf, size_t sz) override;
|
||||
|
||||
/** Accept a connection from a socket
|
||||
* @param s The socket
|
||||
@@ -318,7 +318,7 @@ public:
|
||||
|
||||
static void CheckFile(const Anope::string &filename)
|
||||
{
|
||||
if (!Anope::IsFile(filename.c_str()))
|
||||
if (!Anope::IsFile(filename))
|
||||
{
|
||||
Log() << "File does not exist: " << filename;
|
||||
throw ConfigException("Error loading certificate/private key");
|
||||
@@ -339,7 +339,7 @@ public:
|
||||
GnuTLS::X509CertCredentials *newcred = new GnuTLS::X509CertCredentials(certfile, keyfile);
|
||||
|
||||
// DH params is not mandatory
|
||||
if (Anope::IsFile(dhfile.c_str()))
|
||||
if (Anope::IsFile(dhfile))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -384,9 +384,9 @@ void MySSLService::Init(Socket *s)
|
||||
s->io = new SSLSocketIO();
|
||||
}
|
||||
|
||||
int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
|
||||
ssize_t SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
|
||||
{
|
||||
int ret = gnutls_record_recv(this->sess, buf, sz);
|
||||
ssize_t ret = gnutls_record_recv(this->sess, buf, sz);
|
||||
|
||||
if (ret > 0)
|
||||
TotalRead += ret;
|
||||
@@ -411,9 +411,9 @@ int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
|
||||
ssize_t SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
|
||||
{
|
||||
int ret = gnutls_record_send(this->sess, buf, sz);
|
||||
ssize_t ret = gnutls_record_send(this->sess, buf, sz);
|
||||
|
||||
if (ret > 0)
|
||||
TotalWritten += ret;
|
||||
|
||||
@@ -52,14 +52,14 @@ public:
|
||||
* @param sz How much to read
|
||||
* @return Number of bytes received
|
||||
*/
|
||||
int Recv(Socket *s, char *buf, size_t sz) override;
|
||||
ssize_t Recv(Socket *s, char *buf, size_t sz) override;
|
||||
|
||||
/** Write something to the socket
|
||||
* @param s The socket
|
||||
* @param buf The data to write
|
||||
* @param size The length of the data
|
||||
*/
|
||||
int Send(Socket *s, const char *buf, size_t sz) override;
|
||||
ssize_t Send(Socket *s, const char *buf, size_t sz) override;
|
||||
|
||||
/** Accept a connection from a socket
|
||||
* @param s The socket
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
this->certfile = Anope::ExpandConfig(config->Get<const Anope::string>("cert", "fullchain.pem"));
|
||||
this->keyfile = Anope::ExpandConfig(config->Get<const Anope::string>("key", "privkey.pem"));
|
||||
|
||||
if (Anope::IsFile(this->certfile.c_str()))
|
||||
if (Anope::IsFile(this->certfile))
|
||||
{
|
||||
if (!SSL_CTX_use_certificate_chain_file(client_ctx, this->certfile.c_str()) || !SSL_CTX_use_certificate_chain_file(server_ctx, this->certfile.c_str()))
|
||||
throw ConfigException("Error loading certificate");
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
else
|
||||
Log() << "Unable to open certificate " << this->certfile;
|
||||
|
||||
if (Anope::IsFile(this->keyfile.c_str()))
|
||||
if (Anope::IsFile(this->keyfile))
|
||||
{
|
||||
if (!SSL_CTX_use_PrivateKey_file(client_ctx, this->keyfile.c_str(), SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(server_ctx, this->keyfile.c_str(), SSL_FILETYPE_PEM))
|
||||
throw ConfigException("Error loading private key");
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Anope::IsFile(this->certfile.c_str()))
|
||||
if (Anope::IsFile(this->certfile))
|
||||
throw ConfigException("Error loading private key " + this->keyfile + " - file not found");
|
||||
else
|
||||
Log() << "Unable to open private key " << this->keyfile;
|
||||
@@ -237,7 +237,7 @@ SSLSocketIO::SSLSocketIO()
|
||||
this->sslsock = NULL;
|
||||
}
|
||||
|
||||
int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
|
||||
ssize_t SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
|
||||
{
|
||||
int i = SSL_read(this->sslsock, buf, sz);
|
||||
if (i > 0)
|
||||
@@ -256,7 +256,7 @@ int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
|
||||
return i;
|
||||
}
|
||||
|
||||
int SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
|
||||
ssize_t SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
|
||||
{
|
||||
int i = SSL_write(this->sslsock, buf, sz);
|
||||
if (i > 0)
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ public:
|
||||
}
|
||||
|
||||
// Command requires registered users only
|
||||
if (!cmd->AllowUnregistered() && !u->Account())
|
||||
if (!cmd->AllowUnregistered() && !u->IsIdentified())
|
||||
return;
|
||||
|
||||
if (params.size() < cmd->min_params)
|
||||
|
||||
+1
-1
@@ -192,7 +192,7 @@ public:
|
||||
* to has synced, or we'll get greet-floods when the net
|
||||
* recovers from a netsplit. -GD
|
||||
*/
|
||||
if (!c->ci || !c->ci->bi || !user->server->IsSynced() || !user->Account())
|
||||
if (!c->ci || !c->ci->bi || !user->server->IsSynced() || !user->IsIdentified())
|
||||
return;
|
||||
|
||||
Anope::string *greet = ns_greet.Get(user->Account());
|
||||
|
||||
@@ -157,7 +157,8 @@ public:
|
||||
time_t send_delay = Config->GetModule("memoserv")->Get<time_t>("senddelay");
|
||||
if (Config->GetModule(this->owner)->Get<bool>("memooper") && send_delay > 0 && u && u->lastmemosend + send_delay > Anope::CurTime)
|
||||
{
|
||||
source.Reply(_("Please wait %lu seconds before requesting a new vhost."), (unsigned long)send_delay);
|
||||
auto waitperiod = (u->lastmemosend + send_delay) - Anope::CurTime;
|
||||
source.Reply(_("Please wait %s before requesting a new vhost."), Anope::Duration(waitperiod, source.GetAccount()).c_str());
|
||||
u->lastmemosend = Anope::CurTime;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ void IRC2SQL::OnUserConnect(User *u, bool &exempt)
|
||||
query.SetValue("ident", u->GetIdent());
|
||||
query.SetValue("vident", u->GetVIdent());
|
||||
query.SetValue("secure", u->IsSecurelyConnected() ? "Y" : "N");
|
||||
query.SetValue("account", u->Account() ? u->Account()->display : "");
|
||||
query.SetValue("account", u->IsIdentified() ? u->Account()->display : "");
|
||||
query.SetValue("fingerprint", u->fingerprint);
|
||||
query.SetValue("signon", u->signon);
|
||||
query.SetValue("server", u->server->GetName());
|
||||
@@ -175,7 +175,7 @@ void IRC2SQL::OnUserLogin(User *u)
|
||||
{
|
||||
query = "UPDATE `" + prefix + "user` SET account=@account@ WHERE nick=@nick@";
|
||||
query.SetValue("nick", u->nick);
|
||||
query.SetValue("account", u->Account() ? u->Account()->display : "");
|
||||
query.SetValue("account", u->IsIdentified() ? u->Account()->display : "");
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
|
||||
+14
-14
@@ -80,14 +80,14 @@ void IRC2SQL::CheckTables()
|
||||
if (!this->HasTable(prefix + "server"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "server` ("
|
||||
"`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
|
||||
"`id` int UNSIGNED NOT NULL AUTO_INCREMENT,"
|
||||
"`name` varchar(64) NOT NULL,"
|
||||
"`hops` tinyint(3) NOT NULL,"
|
||||
"`hops` tinyint NOT NULL,"
|
||||
"`comment` varchar(255) NOT NULL,"
|
||||
"`link_time` datetime DEFAULT NULL,"
|
||||
"`split_time` datetime DEFAULT NULL,"
|
||||
"`version` varchar(127) DEFAULT NULL,"
|
||||
"`currentusers` int(15) DEFAULT 0,"
|
||||
"`currentusers` int DEFAULT 0,"
|
||||
"`online` enum('Y','N') NOT NULL DEFAULT 'Y',"
|
||||
"`ulined` enum('Y','N') NOT NULL DEFAULT 'N',"
|
||||
"PRIMARY KEY (`id`),"
|
||||
@@ -98,7 +98,7 @@ void IRC2SQL::CheckTables()
|
||||
if (!this->HasTable(prefix + "chan"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "chan` ("
|
||||
"`chanid` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
|
||||
"`chanid` int UNSIGNED NOT NULL AUTO_INCREMENT,"
|
||||
"`channel` varchar(255) NOT NULL,"
|
||||
"`topic` varchar(512) DEFAULT NULL,"
|
||||
"`topicauthor` varchar(255) DEFAULT NULL,"
|
||||
@@ -112,7 +112,7 @@ void IRC2SQL::CheckTables()
|
||||
if (!this->HasTable(prefix + "user"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "user` ("
|
||||
"`nickid` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
|
||||
"`nickid` int UNSIGNED NOT NULL AUTO_INCREMENT,"
|
||||
"`nick` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`host` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`vhost` varchar(255) NOT NULL DEFAULT '',"
|
||||
@@ -127,7 +127,7 @@ void IRC2SQL::CheckTables()
|
||||
"`fingerprint` varchar(128) NOT NULL DEFAULT '',"
|
||||
"`signon` datetime DEFAULT NULL,"
|
||||
"`server` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`servid` int(11) UNSIGNED NOT NULL DEFAULT '0',"
|
||||
"`servid` int UNSIGNED NOT NULL DEFAULT '0',"
|
||||
"`uuid` varchar(32) NOT NULL DEFAULT '',"
|
||||
"`oper` enum('Y','N') NOT NULL DEFAULT 'N',"
|
||||
"`away` enum('Y','N') NOT NULL DEFAULT 'N',"
|
||||
@@ -147,8 +147,8 @@ void IRC2SQL::CheckTables()
|
||||
if (!this->HasTable(prefix + "ison"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "ison` ("
|
||||
"`nickid` int(11) unsigned NOT NULL default '0',"
|
||||
"`chanid` int(11) unsigned NOT NULL default '0',"
|
||||
"`nickid` int unsigned NOT NULL default '0',"
|
||||
"`chanid` int unsigned NOT NULL default '0',"
|
||||
"`modes` varchar(255) NOT NULL default '',"
|
||||
"PRIMARY KEY (`nickid`,`chanid`),"
|
||||
"KEY `modes` (`modes`)"
|
||||
@@ -159,7 +159,7 @@ void IRC2SQL::CheckTables()
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "maxusers` ("
|
||||
"`name` VARCHAR(255) NOT NULL,"
|
||||
"`maxusers` INT(15) NOT NULL,"
|
||||
"`maxusers` int NOT NULL,"
|
||||
"`maxtime` DATETIME NOT NULL,"
|
||||
"`lastused` DATETIME NOT NULL,"
|
||||
"UNIQUE KEY `name` (`name`)"
|
||||
@@ -200,12 +200,12 @@ void IRC2SQL::CheckTables()
|
||||
"(nick_ varchar(255), host_ varchar(255), vhost_ varchar(255), "
|
||||
"chost_ varchar(255), realname_ varchar(255), ip_ varchar(255), "
|
||||
"ident_ varchar(255), vident_ varchar(255), account_ varchar(255), "
|
||||
"secure_ enum('Y','N'), fingerprint_ varchar(255), signon_ int(15), "
|
||||
"secure_ enum('Y','N'), fingerprint_ varchar(255), signon_ int, "
|
||||
"server_ varchar(255), uuid_ varchar(32), modes_ varchar(255), "
|
||||
"oper_ enum('Y','N')) "
|
||||
"BEGIN "
|
||||
"DECLARE cur int(15);"
|
||||
"DECLARE max int(15);"
|
||||
"DECLARE cur int;"
|
||||
"DECLARE max int;"
|
||||
"INSERT INTO `" + prefix + "user` "
|
||||
"(nick, host, vhost, chost, realname, ip, ident, vident, account, "
|
||||
"secure, fingerprint, signon, server, uuid, modes, oper) "
|
||||
@@ -304,8 +304,8 @@ void IRC2SQL::CheckTables()
|
||||
query = "CREATE PROCEDURE `"+ prefix + "JoinUser`"
|
||||
"(nick_ varchar(255), channel_ varchar(255), modes_ varchar(255)) "
|
||||
"BEGIN "
|
||||
"DECLARE cur int(15);"
|
||||
"DECLARE max int(15);"
|
||||
"DECLARE cur int;"
|
||||
"DECLARE max int;"
|
||||
"INSERT INTO `" + prefix + "ison` (nickid, chanid, modes) "
|
||||
"SELECT u.nickid, c.chanid, modes_ "
|
||||
"FROM " + prefix + "user AS u, " + prefix + "chan AS c "
|
||||
|
||||
@@ -145,7 +145,7 @@ public:
|
||||
{
|
||||
User *u = User::Find(uid);
|
||||
|
||||
if (!u || !u->Account() || r.empty())
|
||||
if (!u || !u->IsIdentified() || r.empty())
|
||||
return;
|
||||
|
||||
try
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
|
||||
void OnResult(const LDAPResult &r) override
|
||||
{
|
||||
if (!u || !u->Account())
|
||||
if (!u || !u->IsIdentified())
|
||||
return;
|
||||
|
||||
NickCore *nc = u->Account();
|
||||
|
||||
@@ -100,8 +100,8 @@ public:
|
||||
{
|
||||
if (ci->AccessFor(cu->user).HasPriv("MEMO"))
|
||||
{
|
||||
if (cu->user->Account() && cu->user->Account()->HasExt("MEMO_RECEIVE"))
|
||||
cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), ci->name.c_str(), mi->memos->size());
|
||||
if (cu->user->IsIdentified() && cu->user->Account()->HasExt("MEMO_RECEIVE"))
|
||||
cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), MemoServ->GetQueryCommand().c_str(), ci->name.c_str(), mi->memos->size());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public:
|
||||
{
|
||||
User *user = User::Find(na->nick, true);
|
||||
if (user && user->IsIdentified())
|
||||
user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), mi->memos->size());
|
||||
user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), MemoServ->GetQueryCommand().c_str(), mi->memos->size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
if (nc->memos.GetMemo(i)->unread)
|
||||
++newcnt;
|
||||
if (newcnt > 0)
|
||||
u->SendMessage(MemoServ, newcnt == 1 ? _("You have 1 new memo.") : _("You have %d new memos."), newcnt);
|
||||
u->SendMessage(MemoServ, newcnt, N_("You have %d new memo.", "You have %d new memos."), newcnt);
|
||||
if (nc->memos.memomax > 0 && nc->memos.memos->size() >= static_cast<unsigned>(nc->memos.memomax))
|
||||
{
|
||||
if (nc->memos.memos->size() > static_cast<unsigned>(nc->memos.memomax))
|
||||
@@ -229,8 +229,8 @@ public:
|
||||
if (!params.empty() || source.c || source.service != *MemoServ)
|
||||
return;
|
||||
source.Reply(_(" \n"
|
||||
"Type \002%s%s HELP \037command\037\002 for help on any of the\n"
|
||||
"above commands."), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str());
|
||||
"Type \002%s HELP \037command\037\002 for help on any of the\n"
|
||||
"above commands."), MemoServ->GetQueryCommand().c_str());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -91,9 +91,9 @@ public:
|
||||
if (Command::FindCommandFromService("memoserv/del", bi, cmd))
|
||||
{
|
||||
if (ci)
|
||||
source.Reply(_("To delete, type: \002%s%s %s %s %d\002"), Config->StrictPrivmsg.c_str(), bi->nick.c_str(), cmd.c_str(), ci->name.c_str(), index + 1);
|
||||
source.Reply(_("To delete, type: \002%s %s %s %d\002"), bi->GetQueryCommand().c_str(), cmd.c_str(), ci->name.c_str(), index + 1);
|
||||
else
|
||||
source.Reply(_("To delete, type: \002%s%s %s %d\002"), Config->StrictPrivmsg.c_str(), bi->nick.c_str(), cmd.c_str(), index + 1);
|
||||
source.Reply(_("To delete, type: \002%s %s %d\002"), bi->GetQueryCommand().c_str(), cmd.c_str(), index + 1);
|
||||
}
|
||||
|
||||
source.Reply("%s", m->text.c_str());
|
||||
|
||||
@@ -56,7 +56,11 @@ public:
|
||||
if (result == MemoServService::MEMO_INVALID_TARGET)
|
||||
source.Reply(_("\002%s\002 is not a registered unforbidden nick or channel."), nick.c_str());
|
||||
else if (result == MemoServService::MEMO_TOO_FAST)
|
||||
source.Reply(_("Please wait %lu seconds before using the %s command again."), Config->GetModule("memoserv")->Get<unsigned long>("senddelay"), source.command.c_str());
|
||||
{
|
||||
auto lastmemosend = source.GetUser() ? source.GetUser()->lastmemosend : 0;
|
||||
auto waitperiod = (lastmemosend + Config->GetModule("memoserv")->Get<unsigned long>("senddelay")) - Anope::CurTime;
|
||||
source.Reply(_("Please wait %s before using the %s command again."), Anope::Duration(waitperiod, source.GetAccount()).c_str(), source.command.c_str());
|
||||
}
|
||||
else if (result == MemoServService::MEMO_TARGET_FULL)
|
||||
source.Reply(_("Sorry, %s currently has too many memos and cannot receive more."), nick.c_str());
|
||||
else
|
||||
|
||||
@@ -55,7 +55,11 @@ public:
|
||||
else if (result == MemoServService::MEMO_INVALID_TARGET)
|
||||
source.Reply(_("\002%s\002 is not a registered unforbidden nick or channel."), nick.c_str());
|
||||
else if (result == MemoServService::MEMO_TOO_FAST)
|
||||
source.Reply(_("Please wait %lu seconds before using the %s command again."), Config->GetModule("memoserv")->Get<unsigned long>("senddelay"), source.command.c_str());
|
||||
{
|
||||
auto lastmemosend = source.GetUser() ? source.GetUser()->lastmemosend : 0;
|
||||
auto waitperiod = (lastmemosend + Config->GetModule("memoserv")->Get<unsigned long>("senddelay")) - Anope::CurTime;
|
||||
source.Reply(_("Please wait %s before using the %s command again."), Anope::Duration(waitperiod, source.GetAccount()).c_str(), source.command.c_str());
|
||||
}
|
||||
else if (result == MemoServService::MEMO_TARGET_FULL)
|
||||
source.Reply(_("Sorry, %s currently has too many memos and cannot receive more."), nick.c_str());
|
||||
}
|
||||
|
||||
@@ -232,8 +232,8 @@ public:
|
||||
" LIMIT Sets the maximum number of memos you can\n"
|
||||
" receive\n"
|
||||
" \n"
|
||||
"Type \002%s%s HELP %s \037option\037\002 for more information\n"
|
||||
"on a specific option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
|
||||
"Type \002%s HELP %s \037option\037\002 for more information\n"
|
||||
"on a specific option."), source.service->GetQueryCommand().c_str(), source.command.c_str());
|
||||
}
|
||||
else if (subcommand.equals_ci("NOTIFY"))
|
||||
source.Reply(_("Syntax: \002NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\002\n"
|
||||
|
||||
@@ -98,7 +98,7 @@ class NickServRelease final
|
||||
|
||||
public:
|
||||
NickServRelease(Module *me, NickAlias *na, time_t delay)
|
||||
: User(na->nick, Config->GetModule("nickserv")->Get<const Anope::string>("enforceruser", "user"), Config->GetModule("nickserv")->Get<const Anope::string>("enforcerhost", Me->GetName()), "", "", Me, "Services Enforcer", Anope::CurTime, "", IRCD->UID_Retrieve(), NULL)
|
||||
: User(na->nick, Config->GetModule(me)->Get<const Anope::string>("enforceruser", "user"), Config->GetModule(me)->Get<const Anope::string>("enforcerhost", Me->GetName()), "", "", Me, "Services Enforcer", Anope::CurTime, "", {}, IRCD->UID_Retrieve(), NULL)
|
||||
, Timer(me, delay)
|
||||
, nick(na->nick)
|
||||
{
|
||||
@@ -140,12 +140,12 @@ class NickServCore final
|
||||
{
|
||||
collided.Unset(na);
|
||||
|
||||
new NickServHeld(this, na, Config->GetModule("nickserv")->Get<time_t>("releasetimeout", "1m"));
|
||||
new NickServHeld(this, na, Config->GetModule(this)->Get<time_t>("releasetimeout", "1m"));
|
||||
|
||||
if (IRCD->CanSVSHold)
|
||||
IRCD->SendSVSHold(na->nick, Config->GetModule("nickserv")->Get<time_t>("releasetimeout", "1m"));
|
||||
IRCD->SendSVSHold(na->nick, Config->GetModule(this)->Get<time_t>("releasetimeout", "1m"));
|
||||
else
|
||||
new NickServRelease(this, na, Config->GetModule("nickserv")->Get<time_t>("releasetimeout", "1m"));
|
||||
new NickServRelease(this, na, Config->GetModule(this)->Get<time_t>("releasetimeout", "1m"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +174,24 @@ public:
|
||||
OnShutdown();
|
||||
}
|
||||
|
||||
bool IsGuestNick(const Anope::string &nick) const override
|
||||
{
|
||||
const auto guestnick = Config->GetModule(this)->Get<Anope::string>("guestnick", "Guest####");
|
||||
if (guestnick.empty())
|
||||
return false; // No guest nick.
|
||||
|
||||
const auto minlen = std::min(nick.length(), guestnick.length());
|
||||
for (size_t idx = 0; idx < minlen; ++idx)
|
||||
{
|
||||
if (guestnick[idx] == '#' && !isdigit(nick[idx]))
|
||||
return false;
|
||||
|
||||
if (Anope::tolower(guestnick[idx]) != Anope::tolower(nick[idx]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Validate(User *u) override
|
||||
{
|
||||
NickAlias *na = NickAlias::Find(u->nick);
|
||||
@@ -195,7 +213,7 @@ public:
|
||||
|
||||
if (!na->nc->HasExt("KILL_IMMED"))
|
||||
{
|
||||
u->SendMessage(NickServ, NICK_IS_SECURE, Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
|
||||
u->SendMessage(NickServ, NICK_IS_SECURE, NickServ->GetQueryCommand().c_str());
|
||||
}
|
||||
if (na->nc->HasExt("KILLPROTECT"))
|
||||
{
|
||||
@@ -238,30 +256,47 @@ public:
|
||||
|
||||
if (IRCD->CanSVSNick)
|
||||
{
|
||||
unsigned nicklen = IRCD->MaxNick;
|
||||
const Anope::string &guestprefix = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest");
|
||||
|
||||
auto guestnickok = false;
|
||||
Anope::string guestnick;
|
||||
|
||||
int i = 0;
|
||||
do
|
||||
for (auto i = 0; i < 10; ++i)
|
||||
{
|
||||
guestnick = guestprefix + Anope::ToString(static_cast<uint16_t>(Anope::RandomNumber()));
|
||||
if (guestnick.length() > nicklen)
|
||||
guestnick = guestnick.substr(0, nicklen);
|
||||
}
|
||||
while (User::Find(guestnick) && i++ < 10);
|
||||
guestnick.clear();
|
||||
for (auto guestnickchr : Config->GetModule(this)->Get<Anope::string>("guestnick", "Guest####").substr(0, IRCD->MaxNick))
|
||||
{
|
||||
if (guestnickchr == '#')
|
||||
guestnick.append(Anope::ToString(abs(Anope::RandomNumber()) % 10));
|
||||
else
|
||||
guestnick.push_back(guestnickchr);
|
||||
}
|
||||
|
||||
if (i == 11)
|
||||
u->Kill(*NickServ, "Services nickname-enforcer kill");
|
||||
else
|
||||
// A guest nick is valid if it is non-empty and is not in use.
|
||||
if (!guestnick.empty() && !User::Find(guestnick, true))
|
||||
{
|
||||
guestnickok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't find a guest nick and the IRCd supports
|
||||
// uids then we should use that as the backup guest
|
||||
// nickname.
|
||||
if (!guestnickok && IRCD->RequiresID)
|
||||
{
|
||||
guestnickok = true;
|
||||
guestnick = u->GetUID();
|
||||
}
|
||||
|
||||
if (guestnickok)
|
||||
{
|
||||
u->SendMessage(*NickServ, _("Your nickname is now being changed to \002%s\002"), guestnick.c_str());
|
||||
IRCD->SendForceNickChange(u, guestnick, Anope::CurTime);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
u->Kill(*NickServ, "Services nickname-enforcer kill");
|
||||
|
||||
// We can't change the user's nickname or we can't find an
|
||||
// acceptable guest nick, give them the boot.
|
||||
u->Kill(*NickServ, "Enforcement of services protected nickname");
|
||||
}
|
||||
|
||||
void Release(NickAlias *na) override
|
||||
@@ -362,8 +397,8 @@ public:
|
||||
u->SendMessage(NickServ, _("You must now supply an email for your nick.\n"
|
||||
"This email will allow you to retrieve your password in\n"
|
||||
"case you forget it."));
|
||||
u->SendMessage(NickServ, _("Type \002%s%s SET EMAIL \037email\037\002 in order to set your email."),
|
||||
Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
|
||||
u->SendMessage(NickServ, _("Type \002%s SET EMAIL \037email\037\002 in order to set your email."),
|
||||
NickServ->GetQueryCommand().c_str());
|
||||
}
|
||||
|
||||
for (auto *c : collides)
|
||||
@@ -400,7 +435,7 @@ public:
|
||||
const NickAlias *na = NickAlias::Find(u->nick);
|
||||
|
||||
const Anope::string &unregistered_notice = Config->GetModule(this)->Get<const Anope::string>("unregistered_notice");
|
||||
if (!Config->GetModule("nickserv")->Get<bool>("nonicknameownership") && !unregistered_notice.empty() && !na && !u->Account())
|
||||
if (!Config->GetModule("nickserv")->Get<bool>("nonicknameownership") && !unregistered_notice.empty() && !na && !u->IsIdentified())
|
||||
u->SendMessage(NickServ, unregistered_notice.replace_all_cs("%n", u->nick));
|
||||
else if (na && !u->IsIdentified(true))
|
||||
this->Validate(u);
|
||||
@@ -465,15 +500,15 @@ public:
|
||||
source.Reply(_("\002%s\002 allows you to register a nickname and\n"
|
||||
"prevent others from using it. The following\n"
|
||||
"commands allow for registration and maintenance of\n"
|
||||
"nicknames; to use them, type \002%s%s \037command\037\002.\n"
|
||||
"nicknames; to use them, type \002%s \037command\037\002.\n"
|
||||
"For more information on a specific command, type\n"
|
||||
"\002%s%s %s \037command\037\002.\n"), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), source.command.c_str());
|
||||
"\002%s %s \037command\037\002.\n"), NickServ->nick.c_str(), NickServ->GetQueryCommand().c_str(), NickServ->GetQueryCommand().c_str(), source.command.c_str());
|
||||
else
|
||||
source.Reply(_("\002%s\002 allows you to register an account.\n"
|
||||
"The following commands allow for registration and maintenance of\n"
|
||||
"accounts; to use them, type \002%s%s \037command\037\002.\n"
|
||||
"accounts; to use them, type \002%s \037command\037\002.\n"
|
||||
"For more information on a specific command, type\n"
|
||||
"\002%s%s %s \037command\037\002.\n"), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), source.command.c_str());
|
||||
"\002%s %s \037command\037\002.\n"), NickServ->nick.c_str(), NickServ->GetQueryCommand().c_str(), NickServ->GetQueryCommand().c_str(), source.command.c_str());
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -486,7 +521,7 @@ public:
|
||||
"Services Operators can also drop any nickname without needing\n"
|
||||
"to identify for the nick, and may view the access list for\n"
|
||||
"any nickname."));
|
||||
time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "90d");
|
||||
time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "1y");
|
||||
if (nickserv_expire >= 86400)
|
||||
source.Reply(_(" \n"
|
||||
"Accounts that are not used anymore are subject to\n"
|
||||
@@ -554,7 +589,7 @@ public:
|
||||
{
|
||||
if (!na->nc->HasExt("UNCONFIRMED"))
|
||||
{
|
||||
time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "90d");
|
||||
time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "1y");
|
||||
if (!na->HasExt("NS_NO_EXPIRE") && nickserv_expire && !Anope::NoExpire && (source.HasPriv("nickserv/auspex") || na->last_seen != Anope::CurTime))
|
||||
info[_("Expires")] = Anope::strftime(na->last_seen + nickserv_expire, source.GetAccount());
|
||||
}
|
||||
|
||||
@@ -425,6 +425,9 @@ public:
|
||||
|
||||
auto *cl = certs.Require(na->nc);
|
||||
cl->AddCert(u->fingerprint);
|
||||
|
||||
auto *NickServ = Config->GetClient("NickServ");
|
||||
u->SendMessage(NickServ, _("Your SSL certificate fingerprint \002%s\002 has been automatically added to your certificate list."), u->fingerprint.c_str());
|
||||
}
|
||||
|
||||
EventReturn OnNickValidate(User *u, NickAlias *na) override
|
||||
|
||||
@@ -72,8 +72,8 @@ public:
|
||||
*code = Anope::Random(15);
|
||||
}
|
||||
|
||||
source.Reply(CONFIRM_DROP, na->nick.c_str(), Config->StrictPrivmsg.c_str(),
|
||||
source.service->nick.c_str(), na->nick.c_str(), code->c_str());
|
||||
source.Reply(CONFIRM_DROP, na->nick.c_str(), source.service->GetQueryCommand().c_str(),
|
||||
na->nick.c_str(), code->c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "module.h"
|
||||
#include "modules/ns_cert.h"
|
||||
|
||||
static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
|
||||
|
||||
class NSGroupRequest final
|
||||
: public IdentifyRequest
|
||||
{
|
||||
@@ -142,13 +144,15 @@ public:
|
||||
}
|
||||
|
||||
NickAlias *target, *na = NickAlias::Find(source.GetNick());
|
||||
const Anope::string &guestnick = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest");
|
||||
time_t reg_delay = Config->GetModule("nickserv")->Get<time_t>("regdelay");
|
||||
unsigned maxaliases = Config->GetModule(this->owner)->Get<unsigned>("maxaliases");
|
||||
if (!(target = NickAlias::Find(nick)))
|
||||
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
|
||||
else if (user && Anope::CurTime < user->lastnickreg + reg_delay)
|
||||
source.Reply(_("Please wait %lu seconds before using the GROUP command again."), (unsigned long)(reg_delay + user->lastnickreg) - Anope::CurTime);
|
||||
{
|
||||
auto waitperiod = (unsigned long)(reg_delay + user->lastnickreg) - Anope::CurTime;
|
||||
source.Reply(_("Please wait %s before using the GROUP command again."), Anope::Duration(waitperiod, source.GetAccount()).c_str());
|
||||
}
|
||||
else if (target->nc->HasExt("NS_SUSPENDED"))
|
||||
{
|
||||
Log(LOG_COMMAND, source, this) << "and tried to group to SUSPENDED nick " << target->nick;
|
||||
@@ -162,12 +166,8 @@ public:
|
||||
source.Reply(NICK_IDENTIFY_REQUIRED);
|
||||
else if (maxaliases && target->nc->aliases->size() >= maxaliases && !target->nc->IsServicesOper())
|
||||
source.Reply(_("There are too many nicks in your group."));
|
||||
else if (source.GetNick().length() <= guestnick.length() + 7 &&
|
||||
source.GetNick().length() >= guestnick.length() + 1 &&
|
||||
!source.GetNick().find_ci(guestnick) && !source.GetNick().substr(guestnick.length()).find_first_not_of("1234567890"))
|
||||
{
|
||||
else if (nickserv && nickserv->IsGuestNick(source.GetNick()))
|
||||
source.Reply(NICK_CANNOT_BE_REGISTERED, source.GetNick().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
bool ok = false;
|
||||
@@ -356,7 +356,7 @@ public:
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
source.Reply(_("%zu nickname(s) in the group."), nc->aliases->size());
|
||||
source.Reply(nc->aliases->size(), N_("%zu nickname in the group.", "%zu nicknames in the group."), nc->aliases->size());
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (u->Account() && na && u->Account() == na->nc)
|
||||
if (u->IsIdentified() && na && u->Account() == na->nc)
|
||||
{
|
||||
source.Reply(_("You are already identified."));
|
||||
return;
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
static bool SendRegmail(User *u, const NickAlias *na, BotInfo *bi);
|
||||
|
||||
static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
|
||||
|
||||
class CommandNSConfirm final
|
||||
: public Command
|
||||
{
|
||||
@@ -133,7 +135,6 @@ public:
|
||||
{
|
||||
User *u = source.GetUser();
|
||||
Anope::string u_nick = source.GetNick();
|
||||
size_t nicklen = u_nick.length();
|
||||
Anope::string pass = params[0];
|
||||
Anope::string email = params.size() > 1 ? params[1] : "";
|
||||
const Anope::string &nsregister = Config->GetModule(this->owner)->Get<const Anope::string>("registration");
|
||||
@@ -154,18 +155,13 @@ public:
|
||||
time_t reg_delay = Config->GetModule("nickserv")->Get<time_t>("regdelay");
|
||||
if (u && !u->HasMode("OPER") && nickregdelay && Anope::CurTime - u->timestamp < nickregdelay)
|
||||
{
|
||||
source.Reply(_("You must have been using this nick for at least %lu seconds to register."),
|
||||
(unsigned long)nickregdelay);
|
||||
auto waitperiod = (u->timestamp + nickregdelay) - Anope::CurTime;
|
||||
source.Reply(_("You must wait %s before registering your nick."),
|
||||
Anope::Duration(waitperiod, source.GetAccount()).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prevent "Guest" nicks from being registered. -TheShadow */
|
||||
|
||||
/* Guest nick can now have a series of between 1 and 7 digits.
|
||||
* --lara
|
||||
*/
|
||||
const Anope::string &guestnick = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest");
|
||||
if (nicklen <= guestnick.length() + 7 && nicklen >= guestnick.length() + 1 && !u_nick.find_ci(guestnick) && u_nick.substr(guestnick.length()).find_first_not_of("1234567890") == Anope::string::npos)
|
||||
if (nickserv && nickserv->IsGuestNick(u_nick))
|
||||
{
|
||||
source.Reply(NICK_CANNOT_BE_REGISTERED, u_nick.c_str());
|
||||
return;
|
||||
@@ -202,8 +198,9 @@ public:
|
||||
this->OnSyntaxError(source, "");
|
||||
else if (u && Anope::CurTime < u->lastnickreg + reg_delay)
|
||||
{
|
||||
source.Reply(_("Please wait %lu seconds before using the REGISTER command again."),
|
||||
(unsigned long)(u->lastnickreg + reg_delay) - Anope::CurTime);
|
||||
auto waitperiod = (unsigned long)(u->lastnickreg + reg_delay) - Anope::CurTime;
|
||||
source.Reply(_("Please wait %s before using the REGISTER command again."),
|
||||
Anope::Duration(waitperiod, source.GetAccount()).c_str());
|
||||
}
|
||||
else if (NickAlias::Find(u_nick) != NULL)
|
||||
source.Reply(NICK_ALREADY_REGISTERED, u_nick.c_str());
|
||||
|
||||
+9
-275
@@ -17,7 +17,7 @@ class CommandNSSet final
|
||||
public:
|
||||
CommandNSSet(Module *creator) : Command(creator, "nickserv/set", 1, 3)
|
||||
{
|
||||
this->SetDesc(_("Set options, including kill protection"));
|
||||
this->SetDesc(_("Set nickname options and information"));
|
||||
this->SetSyntax(_("\037option\037 \037parameters\037"));
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n"
|
||||
"on a specific option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
|
||||
source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information\n"
|
||||
"on a specific option."), source.service->GetQueryCommand().c_str(), this_name.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -100,9 +100,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n"
|
||||
source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information\n"
|
||||
"on a specific option. The options will be set on the given\n"
|
||||
"\037nickname\037."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
|
||||
"\037nickname\037."), source.service->GetQueryCommand().c_str(), this_name.c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -752,252 +752,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSSetKill
|
||||
: public Command
|
||||
{
|
||||
public:
|
||||
CommandNSSetKill(Module *creator, const Anope::string &sname = "nickserv/set/kill", size_t min = 1) : Command(creator, sname, min, min + 1)
|
||||
{
|
||||
this->SetDesc(_("Turn protection on or off"));
|
||||
this->SetSyntax("{ON | QUICK | IMMED | OFF}");
|
||||
}
|
||||
|
||||
void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m)
|
||||
{
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
|
||||
{
|
||||
source.Reply(_("This command may not be used on this network because nickname ownership is disabled."));
|
||||
return;
|
||||
}
|
||||
|
||||
const NickAlias *na = NickAlias::Find(user);
|
||||
if (!na)
|
||||
{
|
||||
source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
|
||||
return;
|
||||
}
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (param.equals_ci("ON"))
|
||||
{
|
||||
nc->Extend<bool>("KILLPROTECT");
|
||||
nc->Shrink<bool>("KILL_QUICK");
|
||||
nc->Shrink<bool>("KILL_IMMED");
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill on for " << nc->display;
|
||||
source.Reply(_("Protection is now \002on\002 for \002%s\002."), nc->display.c_str());
|
||||
}
|
||||
else if (param.equals_ci("QUICK"))
|
||||
{
|
||||
nc->Extend<bool>("KILLPROTECT");
|
||||
nc->Extend<bool>("KILL_QUICK");
|
||||
nc->Shrink<bool>("KILL_IMMED");
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill quick for " << nc->display;
|
||||
source.Reply(_("Protection is now \002on\002 for \002%s\002, with a reduced delay."), nc->display.c_str());
|
||||
}
|
||||
else if (param.equals_ci("IMMED"))
|
||||
{
|
||||
if (Config->GetModule(this->owner)->Get<bool>("allowkillimmed"))
|
||||
{
|
||||
nc->Extend<bool>("KILLPROTECT");
|
||||
nc->Shrink<bool>("KILL_QUICK");
|
||||
nc->Extend<bool>("KILL_IMMED");
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill immed for " << nc->display;
|
||||
source.Reply(_("Protection is now \002on\002 for \002%s\002, with no delay."), nc->display.c_str());
|
||||
}
|
||||
else
|
||||
source.Reply(_("The \002IMMED\002 option is not available on this network."));
|
||||
}
|
||||
else if (param.equals_ci("OFF"))
|
||||
{
|
||||
nc->Shrink<bool>("KILLPROTECT");
|
||||
nc->Shrink<bool>("KILL_QUICK");
|
||||
nc->Shrink<bool>("KILL_IMMED");
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable kill for " << nc->display;
|
||||
source.Reply(_("Protection is now \002off\002 for \002%s\002."), nc->display.c_str());
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "KILL");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
this->Run(source, source.nc->display, params[0]);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Turns the automatic protection option for your nick\n"
|
||||
"on or off. With protection on, if another user\n"
|
||||
"tries to take your nick, they will be given one minute to\n"
|
||||
"change to another nick, after which %s will forcibly change\n"
|
||||
"their nick.\n"
|
||||
" \n"
|
||||
"If you select \002QUICK\002, the user will be given only 20 seconds\n"
|
||||
"to change nicks instead of the usual 60. If you select\n"
|
||||
"\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n"
|
||||
"warned first or given a chance to change their nick; please\n"
|
||||
"do not use this option unless necessary. Also, your\n"
|
||||
"network's administrators may have disabled this option."), source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSSASetKill final
|
||||
: public CommandNSSetKill
|
||||
{
|
||||
public:
|
||||
CommandNSSASetKill(Module *creator) : CommandNSSetKill(creator, "nickserv/saset/kill", 2)
|
||||
{
|
||||
this->ClearSyntax();
|
||||
this->SetSyntax(_("\037nickname\037 {ON | QUICK | IMMED | OFF}"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
this->Run(source, params[0], params[1]);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Turns the automatic protection option for the nick\n"
|
||||
"on or off. With protection on, if another user\n"
|
||||
"tries to take the nick, they will be given one minute to\n"
|
||||
"change to another nick, after which %s will forcibly change\n"
|
||||
"their nick.\n"
|
||||
" \n"
|
||||
"If you select \002QUICK\002, the user will be given only 20 seconds\n"
|
||||
"to change nicks instead of the usual 60. If you select\n"
|
||||
"\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n"
|
||||
"warned first or given a chance to change their nick; please\n"
|
||||
"do not use this option unless necessary. Also, your\n"
|
||||
"network's administrators may have disabled this option."), source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSSetMessage
|
||||
: public Command
|
||||
{
|
||||
public:
|
||||
CommandNSSetMessage(Module *creator, const Anope::string &sname = "nickserv/set/message", size_t min = 1) : Command(creator, sname, min, min + 1)
|
||||
{
|
||||
this->SetDesc(_("Change the communication method of services"));
|
||||
this->SetSyntax("{ON | OFF}");
|
||||
}
|
||||
|
||||
void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m)
|
||||
{
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
return;
|
||||
}
|
||||
|
||||
const NickAlias *na = NickAlias::Find(user);
|
||||
if (!na)
|
||||
{
|
||||
source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
|
||||
return;
|
||||
}
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
if (!Config->GetBlock("options")->Get<bool>("useprivmsg"))
|
||||
{
|
||||
source.Reply(_("You cannot %s on this network."), source.command.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (param.equals_ci("ON"))
|
||||
{
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable " << source.command << " for " << nc->display;
|
||||
nc->Extend<bool>("MSG");
|
||||
source.Reply(_("Services will now reply to \002%s\002 with \002messages\002."), nc->display.c_str());
|
||||
}
|
||||
else if (param.equals_ci("OFF"))
|
||||
{
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable " << source.command << " for " << nc->display;
|
||||
nc->Shrink<bool>("MSG");
|
||||
source.Reply(_("Services will now reply to \002%s\002 with \002notices\002."), nc->display.c_str());
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "MSG");
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
this->Run(source, source.nc->display, params[0]);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
Anope::string cmd = source.command;
|
||||
size_t i = cmd.find_last_of(' ');
|
||||
if (i != Anope::string::npos)
|
||||
cmd = cmd.substr(i + 1);
|
||||
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Allows you to choose the way services are communicating with\n"
|
||||
"you. With \002%s\002 set, services will use messages, else they'll\n"
|
||||
"use notices."), cmd.upper().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnServHelp(CommandSource &source) override
|
||||
{
|
||||
if (Config->GetBlock("options")->Get<bool>("useprivmsg"))
|
||||
Command::OnServHelp(source);
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSSASetMessage final
|
||||
: public CommandNSSetMessage
|
||||
{
|
||||
public:
|
||||
CommandNSSASetMessage(Module *creator) : CommandNSSetMessage(creator, "nickserv/saset/message", 2)
|
||||
{
|
||||
this->ClearSyntax();
|
||||
this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Allows you to choose the way services are communicating with\n"
|
||||
"the given user. With \002MSG\002 set, services will use messages,\n"
|
||||
"else they'll use notices."));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
this->Run(source, params[0], params[1]);
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSSASetNoexpire final
|
||||
: public Command
|
||||
{
|
||||
@@ -1072,19 +826,13 @@ class NSSet final
|
||||
CommandNSSetKeepModes commandnssetkeepmodes;
|
||||
CommandNSSASetKeepModes commandnssasetkeepmodes;
|
||||
|
||||
CommandNSSetKill commandnssetkill;
|
||||
CommandNSSASetKill commandnssasetkill;
|
||||
|
||||
CommandNSSetMessage commandnssetmessage;
|
||||
CommandNSSASetMessage commandnssasetmessage;
|
||||
|
||||
CommandNSSetPassword commandnssetpassword;
|
||||
CommandNSSASetPassword commandnssasetpassword;
|
||||
|
||||
CommandNSSASetNoexpire commandnssasetnoexpire;
|
||||
|
||||
SerializableExtensibleItem<bool> autoop, neverop, killprotect, kill_quick, kill_immed,
|
||||
message, noexpire;
|
||||
SerializableExtensibleItem<bool> autoop, neverop, noexpire;
|
||||
|
||||
struct KeepModes final
|
||||
: SerializableExtensibleItem<bool>
|
||||
@@ -1144,19 +892,13 @@ public:
|
||||
commandnssetdisplay(this), commandnssasetdisplay(this),
|
||||
commandnssetemail(this), commandnssasetemail(this),
|
||||
commandnssetkeepmodes(this), commandnssasetkeepmodes(this),
|
||||
commandnssetkill(this), commandnssasetkill(this),
|
||||
commandnssetmessage(this), commandnssasetmessage(this),
|
||||
commandnssetpassword(this), commandnssasetpassword(this),
|
||||
commandnssasetnoexpire(this),
|
||||
|
||||
autoop(this, "AUTOOP"), neverop(this, "NEVEROP"),
|
||||
killprotect(this, "KILLPROTECT"), kill_quick(this, "KILL_QUICK"),
|
||||
kill_immed(this, "KILL_IMMED"), message(this, "MSG"),
|
||||
noexpire(this, "NS_NO_EXPIRE"),
|
||||
|
||||
keep_modes(this, "NS_KEEP_MODES"), ns_set_email(this, "ns_set_email")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) override
|
||||
@@ -1187,7 +929,7 @@ public:
|
||||
if (chan->ci)
|
||||
{
|
||||
/* Only give modes if autoop is set */
|
||||
give_modes &= !user->Account() || autoop.HasExt(user->Account());
|
||||
give_modes &= !user->IsIdentified() || autoop.HasExt(user->Account());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1202,14 +944,6 @@ public:
|
||||
if (!show_hidden)
|
||||
return;
|
||||
|
||||
if (kill_immed.HasExt(na->nc))
|
||||
info.AddOption(_("Immediate protection"));
|
||||
else if (kill_quick.HasExt(na->nc))
|
||||
info.AddOption(_("Quick protection"));
|
||||
else if (killprotect.HasExt(na->nc))
|
||||
info.AddOption(_("Protection"));
|
||||
if (message.HasExt(na->nc))
|
||||
info.AddOption(_("Message mode"));
|
||||
if (autoop.HasExt(na->nc))
|
||||
info.AddOption(_("Auto-op"));
|
||||
if (neverop.HasExt(na->nc))
|
||||
@@ -1222,13 +956,13 @@ public:
|
||||
|
||||
void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) override
|
||||
{
|
||||
if (u->Account() && setter.GetUser() == u)
|
||||
if (u->IsIdentified() && setter.GetUser() == u)
|
||||
u->Account()->last_modes = u->GetModeList();
|
||||
}
|
||||
|
||||
void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) override
|
||||
{
|
||||
if (u->Account() && setter.GetUser() == u)
|
||||
if (u->IsIdentified() && setter.GetUser() == u)
|
||||
u->Account()->last_modes = u->GetModeList();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/* NickServ core functions
|
||||
*
|
||||
* (C) 2003-2024 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.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class CommandNSSetKill
|
||||
: public Command
|
||||
{
|
||||
public:
|
||||
CommandNSSetKill(Module *creator, const Anope::string &sname = "nickserv/set/kill", size_t min = 1)
|
||||
: Command(creator, sname, min, min + 1)
|
||||
{
|
||||
this->SetDesc(_("Turn protection on or off"));
|
||||
this->SetSyntax("{ON | QUICK | IMMED | OFF}");
|
||||
}
|
||||
|
||||
void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m)
|
||||
{
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
|
||||
{
|
||||
source.Reply(_("This command may not be used on this network because nickname ownership is disabled."));
|
||||
return;
|
||||
}
|
||||
|
||||
const NickAlias *na = NickAlias::Find(user);
|
||||
if (!na)
|
||||
{
|
||||
source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
|
||||
return;
|
||||
}
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (param.equals_ci("ON"))
|
||||
{
|
||||
nc->Extend<bool>("KILLPROTECT");
|
||||
nc->Shrink<bool>("KILL_QUICK");
|
||||
nc->Shrink<bool>("KILL_IMMED");
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill on for " << nc->display;
|
||||
source.Reply(_("Protection is now \002on\002 for \002%s\002."), nc->display.c_str());
|
||||
}
|
||||
else if (param.equals_ci("QUICK"))
|
||||
{
|
||||
nc->Extend<bool>("KILLPROTECT");
|
||||
nc->Extend<bool>("KILL_QUICK");
|
||||
nc->Shrink<bool>("KILL_IMMED");
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill quick for " << nc->display;
|
||||
source.Reply(_("Protection is now \002on\002 for \002%s\002, with a reduced delay."), nc->display.c_str());
|
||||
}
|
||||
else if (param.equals_ci("IMMED"))
|
||||
{
|
||||
if (Config->GetModule(this->owner)->Get<bool>("allowkillimmed"))
|
||||
{
|
||||
nc->Extend<bool>("KILLPROTECT");
|
||||
nc->Shrink<bool>("KILL_QUICK");
|
||||
nc->Extend<bool>("KILL_IMMED");
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill immed for " << nc->display;
|
||||
source.Reply(_("Protection is now \002on\002 for \002%s\002, with no delay."), nc->display.c_str());
|
||||
}
|
||||
else
|
||||
source.Reply(_("The \002IMMED\002 option is not available on this network."));
|
||||
}
|
||||
else if (param.equals_ci("OFF"))
|
||||
{
|
||||
nc->Shrink<bool>("KILLPROTECT");
|
||||
nc->Shrink<bool>("KILL_QUICK");
|
||||
nc->Shrink<bool>("KILL_IMMED");
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable kill for " << nc->display;
|
||||
source.Reply(_("Protection is now \002off\002 for \002%s\002."), nc->display.c_str());
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "KILL");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
this->Run(source, source.nc->display, params[0]);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Turns the automatic protection option for your nick\n"
|
||||
"on or off. With protection on, if another user\n"
|
||||
"tries to take your nick, they will be given one minute to\n"
|
||||
"change to another nick, after which %s will forcibly change\n"
|
||||
"their nick.\n"
|
||||
" \n"
|
||||
"If you select \002QUICK\002, the user will be given only 20 seconds\n"
|
||||
"to change nicks instead of the usual 60. If you select\n"
|
||||
"\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n"
|
||||
"warned first or given a chance to change their nick; please\n"
|
||||
"do not use this option unless necessary. Also, your\n"
|
||||
"network's administrators may have disabled this option."), source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSSASetKill final
|
||||
: public CommandNSSetKill
|
||||
{
|
||||
public:
|
||||
CommandNSSASetKill(Module *creator)
|
||||
: CommandNSSetKill(creator, "nickserv/saset/kill", 2)
|
||||
{
|
||||
this->ClearSyntax();
|
||||
this->SetSyntax(_("\037nickname\037 {ON | QUICK | IMMED | OFF}"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
this->Run(source, params[0], params[1]);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Turns the automatic protection option for the nick\n"
|
||||
"on or off. With protection on, if another user\n"
|
||||
"tries to take the nick, they will be given one minute to\n"
|
||||
"change to another nick, after which %s will forcibly change\n"
|
||||
"their nick.\n"
|
||||
" \n"
|
||||
"If you select \002QUICK\002, the user will be given only 20 seconds\n"
|
||||
"to change nicks instead of the usual 60. If you select\n"
|
||||
"\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n"
|
||||
"warned first or given a chance to change their nick; please\n"
|
||||
"do not use this option unless necessary. Also, your\n"
|
||||
"network's administrators may have disabled this option."), source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class NSSetKill final
|
||||
: public Module
|
||||
{
|
||||
private:
|
||||
CommandNSSetKill commandnssetkill;
|
||||
CommandNSSASetKill commandnssasetkill;
|
||||
SerializableExtensibleItem<bool> killprotect, kill_quick, kill_immed;
|
||||
|
||||
public:
|
||||
NSSetKill(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandnssetkill(this)
|
||||
, commandnssasetkill(this)
|
||||
, killprotect(this, "KILLPROTECT")
|
||||
, kill_quick(this, "KILL_QUICK")
|
||||
, kill_immed(this, "KILL_IMMED")
|
||||
{
|
||||
}
|
||||
|
||||
void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
|
||||
{
|
||||
if (!show_hidden)
|
||||
return;
|
||||
|
||||
if (kill_immed.HasExt(na->nc))
|
||||
info.AddOption(_("Immediate protection"));
|
||||
else if (kill_quick.HasExt(na->nc))
|
||||
info.AddOption(_("Quick protection"));
|
||||
else if (killprotect.HasExt(na->nc))
|
||||
info.AddOption(_("Protection"));
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(NSSetKill)
|
||||
@@ -14,9 +14,13 @@
|
||||
class CommandNSSetLanguage
|
||||
: public Command
|
||||
{
|
||||
protected:
|
||||
Anope::map<Anope::string> &languages;
|
||||
|
||||
public:
|
||||
CommandNSSetLanguage(Module *creator, const Anope::string &sname = "nickserv/set/language", size_t min = 1)
|
||||
CommandNSSetLanguage(Module *creator, Anope::map<Anope::string> &langs, const Anope::string &sname = "nickserv/set/language", size_t min = 1)
|
||||
: Command(creator, sname, min, min + 1)
|
||||
, languages(langs)
|
||||
{
|
||||
this->SetDesc(_("Set the language services will use when messaging you"));
|
||||
this->SetSyntax(_("\037language\037"));
|
||||
@@ -43,27 +47,35 @@ public:
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (param != "en_US")
|
||||
auto lang = languages.end();
|
||||
for (auto it = languages.begin(); it != languages.end(); ++it)
|
||||
{
|
||||
for (unsigned j = 0; j < Language::Languages.size(); ++j)
|
||||
auto &[langcode, langname] = *it;
|
||||
if (langcode.find_ci(param) != 0)
|
||||
continue; // Language does not match.
|
||||
|
||||
if (lang != languages.end())
|
||||
{
|
||||
if (Language::Languages[j] == param)
|
||||
break;
|
||||
else if (j + 1 == Language::Languages.size())
|
||||
{
|
||||
this->OnSyntaxError(source, "");
|
||||
return;
|
||||
}
|
||||
source.Reply(_("Multiple languages matched \002%s\002. Please be more specific."), param.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
lang = it;
|
||||
}
|
||||
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the language of " << nc->display << " to " << param;
|
||||
if (lang == languages.end())
|
||||
{
|
||||
this->OnSyntaxError(source, "");
|
||||
return;
|
||||
}
|
||||
|
||||
nc->language = param;
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the language of " << nc->display << " to " << lang->first;
|
||||
|
||||
nc->language = lang->first;
|
||||
if (source.GetAccount() == nc)
|
||||
source.Reply(_("Language changed to \002English\002."));
|
||||
source.Reply(_("Language changed to \002%s\002."), lang->second.c_str());
|
||||
else
|
||||
source.Reply(_("Language for \002%s\002 changed to \002%s\002."), nc->display.c_str(), Language::Translate(param.c_str(), _("English")));
|
||||
source.Reply(_("Language for \002%s\002 changed to \002%s\002."), nc->display.c_str(), lang->second.c_str());
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶m) override
|
||||
@@ -80,13 +92,8 @@ public:
|
||||
"\037language\037 should be chosen from the following list of\n"
|
||||
"supported languages:"));
|
||||
|
||||
source.Reply(" en_US (English)");
|
||||
for (const auto &language : Language::Languages)
|
||||
{
|
||||
const Anope::string &langname = Language::Translate(language.c_str(), _("English"));
|
||||
if (langname != "English")
|
||||
source.Reply(" %s (%s)", language.c_str(), langname.c_str());
|
||||
}
|
||||
for (const auto &[langcode, langname] : languages)
|
||||
source.Reply(" %s (%s)", langcode.c_str(), langname.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -96,8 +103,8 @@ class CommandNSSASetLanguage final
|
||||
: public CommandNSSetLanguage
|
||||
{
|
||||
public:
|
||||
CommandNSSASetLanguage(Module *creator)
|
||||
: CommandNSSetLanguage(creator, "nickserv/saset/language", 2)
|
||||
CommandNSSASetLanguage(Module *creator, Anope::map<Anope::string> &langs)
|
||||
: CommandNSSetLanguage(creator, langs, "nickserv/saset/language", 2)
|
||||
{
|
||||
this->ClearSyntax();
|
||||
this->SetSyntax(_("\037nickname\037 \037language\037"));
|
||||
@@ -116,13 +123,10 @@ public:
|
||||
"the given user (for example, when responding to a command they send).\n"
|
||||
"\037language\037 should be chosen from the following list of\n"
|
||||
"supported languages:"));
|
||||
source.Reply(" en_US (English)");
|
||||
for (const auto &language : Language::Languages)
|
||||
{
|
||||
const Anope::string &langname = Language::Translate(language.c_str(), _("English"));
|
||||
if (langname != "English")
|
||||
source.Reply(" %s (%s)", language.c_str(), langname.c_str());
|
||||
}
|
||||
|
||||
for (const auto &[langcode, langname] : languages)
|
||||
source.Reply(" %s (%s)", langcode.c_str(), langname.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -133,16 +137,23 @@ class NSSetLanguage final
|
||||
private:
|
||||
CommandNSSetLanguage commandnssetlanguage;
|
||||
CommandNSSASetLanguage commandnssasetlanguage;
|
||||
Anope::map<Anope::string> languages;
|
||||
|
||||
public:
|
||||
NSSetLanguage(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandnssetlanguage(this)
|
||||
, commandnssasetlanguage(this)
|
||||
, commandnssetlanguage(this, languages)
|
||||
, commandnssasetlanguage(this, languages)
|
||||
{
|
||||
#ifndef HAVE_LOCALIZATION
|
||||
throw ModuleException("Anope was not built with localization support");
|
||||
#endif
|
||||
|
||||
// Build a list of languages. This only needs to happen once as we
|
||||
// only load the languages on boot.
|
||||
languages.emplace("en_US.UTF-8", "English");
|
||||
for (const auto &language : Language::Languages)
|
||||
languages.emplace(language, Language::Translate(language.c_str(), _("English")));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/* NickServ core functions
|
||||
*
|
||||
* (C) 2003-2024 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.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class CommandNSSetMessage
|
||||
: public Command
|
||||
{
|
||||
public:
|
||||
CommandNSSetMessage(Module *creator, const Anope::string &sname = "nickserv/set/message", size_t min = 1)
|
||||
: Command(creator, sname, min, min + 1)
|
||||
{
|
||||
this->SetDesc(_("Change the communication method of services"));
|
||||
this->SetSyntax("{ON | OFF}");
|
||||
}
|
||||
|
||||
void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m)
|
||||
{
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
return;
|
||||
}
|
||||
|
||||
const NickAlias *na = NickAlias::Find(user);
|
||||
if (!na)
|
||||
{
|
||||
source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
|
||||
return;
|
||||
}
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return;
|
||||
|
||||
if (param.equals_ci("ON"))
|
||||
{
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable " << source.command << " for " << nc->display;
|
||||
nc->Extend<bool>("MSG");
|
||||
source.Reply(_("Services will now reply to \002%s\002 with \002messages\002."), nc->display.c_str());
|
||||
}
|
||||
else if (param.equals_ci("OFF"))
|
||||
{
|
||||
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable " << source.command << " for " << nc->display;
|
||||
nc->Shrink<bool>("MSG");
|
||||
source.Reply(_("Services will now reply to \002%s\002 with \002notices\002."), nc->display.c_str());
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "MSG");
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
this->Run(source, source.nc->display, params[0]);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
Anope::string cmd = source.command;
|
||||
size_t i = cmd.find_last_of(' ');
|
||||
if (i != Anope::string::npos)
|
||||
cmd = cmd.substr(i + 1);
|
||||
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Allows you to choose the way services are communicating with\n"
|
||||
"you. With \002%s\002 set, services will use messages, else they'll\n"
|
||||
"use notices."), cmd.upper().c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSSASetMessage final
|
||||
: public CommandNSSetMessage
|
||||
{
|
||||
public:
|
||||
CommandNSSASetMessage(Module *creator) : CommandNSSetMessage(creator, "nickserv/saset/message", 2)
|
||||
{
|
||||
this->ClearSyntax();
|
||||
this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Allows you to choose the way services are communicating with\n"
|
||||
"the given user. With \002MSG\002 set, services will use messages,\n"
|
||||
"else they'll use notices."));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
this->Run(source, params[0], params[1]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class NSSetMessage final
|
||||
: public Module
|
||||
{
|
||||
private:
|
||||
CommandNSSetMessage commandnssetmessage;
|
||||
CommandNSSASetMessage commandnssasetmessage;
|
||||
SerializableExtensibleItem<bool> message;
|
||||
|
||||
public:
|
||||
NSSetMessage(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandnssetmessage(this)
|
||||
, commandnssasetmessage(this)
|
||||
, message(this, "MSG")
|
||||
{
|
||||
}
|
||||
|
||||
void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
|
||||
{
|
||||
if (!show_hidden)
|
||||
return;
|
||||
if (message.HasExt(na->nc))
|
||||
info.AddOption(_("Message mode"));
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(NSSetMessage)
|
||||
@@ -292,7 +292,7 @@ public:
|
||||
delete na;
|
||||
}
|
||||
|
||||
source.Reply(_("\002%d\002 nickname(s) dropped."), na_matches);
|
||||
source.Reply(na_matches, N_("\002%d\002 nickname dropped.", "\002%d\002 nicknames dropped."), na_matches);
|
||||
break;
|
||||
}
|
||||
case FT_CHAN:
|
||||
|
||||
@@ -312,12 +312,8 @@ struct IRCDMessageMode final
|
||||
Channel *c = Channel::Find(params[0]);
|
||||
auto ts = IRCD->ExtractTimestamp(params[1]);
|
||||
|
||||
Anope::string modes = params[2];
|
||||
for (unsigned int i = 3; i < params.size(); ++i)
|
||||
modes += " " + params[i];
|
||||
|
||||
if (c)
|
||||
c->SetModesInternal(source, modes, ts);
|
||||
c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() }, ts);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -400,11 +396,12 @@ struct IRCDMessageSJoin final
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
Anope::string modes;
|
||||
std::vector<Anope::string> modeparams;
|
||||
if (params.size() >= 4)
|
||||
for (unsigned i = 2; i < params.size(); ++i)
|
||||
modes += " " + params[i];
|
||||
if (!modes.empty())
|
||||
modes.erase(modes.begin());
|
||||
{
|
||||
modes = params[2];
|
||||
modeparams = { params.begin() + 3, params.end() };
|
||||
}
|
||||
|
||||
std::list<Message::Join::SJoinUser> users;
|
||||
|
||||
@@ -445,7 +442,7 @@ struct IRCDMessageSJoin final
|
||||
}
|
||||
|
||||
auto ts = IRCD->ExtractTimestamp(params[0]);
|
||||
Message::Join::SJoin(source, params[1], ts, modes, users);
|
||||
Message::Join::SJoin(source, params[1], ts, modes, modeparams, users);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -547,14 +547,6 @@ struct IRCDMessageSJoin final
|
||||
/* :0MC SJOIN 1654877335 #nether +nt :@0MCAAAAAB +0MCAAAAAC */
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
Anope::string modes;
|
||||
|
||||
for (unsigned i = 2; i < params.size() - 1; ++i)
|
||||
modes += " " + params[i];
|
||||
|
||||
if (!modes.empty())
|
||||
modes.erase(modes.begin());
|
||||
|
||||
std::list<Message::Join::SJoinUser> users;
|
||||
|
||||
spacesepstream sep(params[params.size() - 1]);
|
||||
@@ -582,7 +574,7 @@ struct IRCDMessageSJoin final
|
||||
}
|
||||
|
||||
auto ts = IRCD->ExtractTimestamp(params[0]);
|
||||
Message::Join::SJoin(source, params[1], ts, modes, users);
|
||||
Message::Join::SJoin(source, params[1], ts, params[2], { params.begin() + 3, params.end() - 1 }, users);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -637,13 +629,9 @@ struct IRCDMessageTMode final
|
||||
{
|
||||
auto ts = IRCD->ExtractTimestamp(params[0]);
|
||||
Channel *c = Channel::Find(params[1]);
|
||||
Anope::string modes = params[2];
|
||||
|
||||
for (unsigned i = 3; i < params.size(); ++i)
|
||||
modes += " " + params[i];
|
||||
|
||||
if (c)
|
||||
c->SetModesInternal(source, modes, ts);
|
||||
c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() }, ts);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ struct SASLUser final
|
||||
|
||||
namespace
|
||||
{
|
||||
/** Whether we should send extbans using their named form. */
|
||||
bool named_extbans = false;
|
||||
|
||||
// The SID of a server we are waiting to squit.
|
||||
Anope::string rsquit_id;
|
||||
|
||||
@@ -102,7 +105,7 @@ class InspIRCdProto final
|
||||
private:
|
||||
static Anope::string GetAccountNicks(NickAlias* na)
|
||||
{
|
||||
if (!na)
|
||||
if (!na || Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
|
||||
return {};
|
||||
|
||||
Anope::string nicks;
|
||||
@@ -637,6 +640,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void SendOper(User *u) override
|
||||
{
|
||||
if (spanningtree_proto_ver < 1206)
|
||||
return; // We can't force an oper on this version.
|
||||
|
||||
const Anope::map<Anope::string> tags = {
|
||||
{ "~automatic", "" },
|
||||
};
|
||||
Uplink::Send(tags, "SVSOPER", u->GetUID(), u->Account()->o->ot->GetName());
|
||||
}
|
||||
|
||||
bool IsExtbanValid(const Anope::string &mask) override
|
||||
{
|
||||
bool inverted;
|
||||
@@ -712,7 +726,8 @@ namespace InspIRCdExtBan
|
||||
|
||||
ChannelMode *Wrap(Anope::string ¶m) override
|
||||
{
|
||||
param = Anope::string(xbchar) + ":" + param;
|
||||
auto xbprefix = named_extbans || !xbchar ? xbname : Anope::string(xbchar);
|
||||
param = xbprefix + ":" + param;
|
||||
return ChannelModeVirtual<ChannelModeList>::Wrap(param);
|
||||
}
|
||||
|
||||
@@ -746,10 +761,7 @@ namespace InspIRCdExtBan
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
|
||||
return Entry(this->name, real_mask).Matches(u);
|
||||
return Entry(this->name, e->GetMask()).Matches(u);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -764,10 +776,7 @@ namespace InspIRCdExtBan
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
|
||||
Anope::string channel = mask.substr(2);
|
||||
|
||||
auto channel = e->GetMask();
|
||||
ChannelMode *cm = NULL;
|
||||
if (channel[0] != '#')
|
||||
{
|
||||
@@ -802,10 +811,7 @@ namespace InspIRCdExtBan
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
|
||||
return u->IsIdentified() && real_mask.equals_ci(u->Account()->display);
|
||||
return u->IsIdentified() && e->GetMask().equals_ci(u->Account()->display);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -820,9 +826,7 @@ namespace InspIRCdExtBan
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
return Anope::Match(u->realname, real_mask);
|
||||
return Anope::Match(u->realname, e->GetMask());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -837,9 +841,7 @@ namespace InspIRCdExtBan
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
return Anope::Match(u->server->GetName(), real_mask);
|
||||
return Anope::Match(u->server->GetName(), e->GetMask());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -854,9 +856,7 @@ namespace InspIRCdExtBan
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
return !u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask);
|
||||
return !u->fingerprint.empty() && Anope::Match(u->fingerprint, e->GetMask());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -871,9 +871,7 @@ namespace InspIRCdExtBan
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
return !u->Account() && Entry("BAN", real_mask).Matches(u);
|
||||
return !u->Account() && Entry(this->base, e->GetMask()).Matches(u);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -892,9 +890,7 @@ namespace InspIRCdExtBan
|
||||
if (!opertype)
|
||||
return false; // Not an operator.
|
||||
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
return Anope::Match(opertype->replace_all_cs(' ', '_'), real_mask);
|
||||
return Anope::Match(opertype->replace_all_cs(' ', '_'), e->GetMask());
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1080,19 +1076,25 @@ struct IRCDMessageCapab final
|
||||
|
||||
static bool ParseExtBan(const Anope::string &token, ExtBanInfo &extban)
|
||||
{
|
||||
// acting:foo=f matching:foo=f
|
||||
// A B A B
|
||||
// acting:foo=f matching:bar=b matching:baz
|
||||
// A B A B A
|
||||
auto a = token.find(':');
|
||||
if (a == Anope::string::npos)
|
||||
return false;
|
||||
|
||||
auto b = token.find(':', a + 1);
|
||||
auto b = token.find('=', a + 1);
|
||||
if (b == Anope::string::npos)
|
||||
return false;
|
||||
|
||||
{
|
||||
// ExtBan only has a name.
|
||||
extban.name = token.substr(a + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ExtBan has a name and letter.
|
||||
extban.name = token.substr(a + 1, b - a - 1);
|
||||
extban.letter = token[b + 1];
|
||||
}
|
||||
extban.type = token.substr(0, a);
|
||||
extban.name = token.substr(a + 1, b - a - 1);
|
||||
extban.letter = token[b + 1];
|
||||
|
||||
if (Anope::ProtocolDebug)
|
||||
Log(LOG_DEBUG) << "Parsed extban: type=" << extban.type << " name=" << extban.name << " letter=" << extban.letter;
|
||||
@@ -1562,6 +1564,8 @@ struct IRCDMessageCapab final
|
||||
auto [tokname, tokvalue] = ParseCapability(capab);
|
||||
if (tokname == "CHALLENGE")
|
||||
challenge = tokvalue;
|
||||
if (tokname == "EXTBANFORMAT")
|
||||
named_extbans = tokvalue.equals_ci("any") || tokvalue.equals_ci("name");
|
||||
else if (tokname == "MAXCHANNEL")
|
||||
IRCD->MaxChannel = Anope::Convert<size_t>(tokvalue, IRCD->MaxChannel);
|
||||
else if (tokname == "MAXHOST")
|
||||
@@ -2045,15 +2049,6 @@ struct IRCDMessageFJoin final
|
||||
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
Anope::string modes;
|
||||
if (params.size() >= 3)
|
||||
{
|
||||
for (unsigned i = 2; i < params.size() - 1; ++i)
|
||||
modes += " " + params[i];
|
||||
if (!modes.empty())
|
||||
modes.erase(modes.begin());
|
||||
}
|
||||
|
||||
std::list<Message::Join::SJoinUser> users;
|
||||
|
||||
spacesepstream sep(params[params.size() - 1]);
|
||||
@@ -2091,7 +2086,7 @@ struct IRCDMessageFJoin final
|
||||
}
|
||||
|
||||
auto ts = IRCD->ExtractTimestamp(params[1]);
|
||||
Message::Join::SJoin(source, params[0], ts, modes, users);
|
||||
Message::Join::SJoin(source, params[0], ts, params[2], { params.begin() + 3, params.end() - 1 }, users);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2103,15 +2098,10 @@ struct IRCDMessageFMode final
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
/* :source FMODE #test 12345678 +nto foo */
|
||||
|
||||
Anope::string modes = params[2];
|
||||
for (unsigned n = 3; n < params.size(); ++n)
|
||||
modes += " " + params[n];
|
||||
|
||||
Channel *c = Channel::Find(params[0]);
|
||||
auto ts = IRCD->ExtractTimestamp(params[1]);
|
||||
if (c)
|
||||
c->SetModesInternal(source, modes, ts);
|
||||
c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() }, ts);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2144,12 +2134,12 @@ struct IRCDMessageIdle final
|
||||
{
|
||||
BotInfo *bi = BotInfo::Find(params[0]);
|
||||
if (bi)
|
||||
Uplink::Send(bi, "IDLE", source.GetSource(), Anope::StartTime, Anope::CurTime - bi->lastmsg);
|
||||
Uplink::Send(bi, "IDLE", source.GetSource(), bi->signon, Anope::CurTime - bi->lastmsg);
|
||||
else
|
||||
{
|
||||
User *u = User::Find(params[0]);
|
||||
if (u && u->server == Me)
|
||||
Uplink::Send(u, "IDLE", source.GetSource(), Anope::StartTime, 0);
|
||||
Uplink::Send(u, "IDLE", source.GetSource(), u->signon, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -2187,7 +2177,7 @@ struct IRCDMessageIJoin final
|
||||
|
||||
std::list<Message::Join::SJoinUser> users;
|
||||
users.push_back(user);
|
||||
Message::Join::SJoin(source, params[0], chants, "", users);
|
||||
Message::Join::SJoin(source, params[0], chants, "", {}, users);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2239,12 +2229,8 @@ struct IRCDMessageMode final
|
||||
{
|
||||
Channel *c = Channel::Find(params[0]);
|
||||
|
||||
Anope::string modes = params[1];
|
||||
for (unsigned n = 2; n < params.size(); ++n)
|
||||
modes += " " + params[n];
|
||||
|
||||
if (c)
|
||||
c->SetModesInternal(source, modes);
|
||||
c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2404,10 +2390,6 @@ struct IRCDMessageUID final
|
||||
size_t offset = params[8][0] == '+' ? 0 : 1;
|
||||
auto ts = IRCD->ExtractTimestamp(params[1]);
|
||||
|
||||
Anope::string modes = params[8+offset];
|
||||
for (unsigned i = 9+offset; i < params.size() - 1; ++i)
|
||||
modes += " " + params[i];
|
||||
|
||||
NickAlias *na = NULL;
|
||||
if (SASL::sasl)
|
||||
for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();)
|
||||
@@ -2425,7 +2407,7 @@ struct IRCDMessageUID final
|
||||
++it;
|
||||
}
|
||||
|
||||
User *u = User::OnIntroduce(params[2], params[5+offset], params[3], params[4], params[6+offset], source.GetServer(), params[params.size() - 1], ts, modes, params[0], na ? *na->nc : NULL);
|
||||
auto *u = User::OnIntroduce(params[2], params[5+offset], params[3], params[4], params[6+offset], source.GetServer(), params[params.size() - 1], ts, params[8 + offset], params[0], na ? *na->nc : NULL, { params.begin() + 9 + offset, params.end() - 1 });
|
||||
if (u)
|
||||
u->signon = IRCD->ExtractTimestamp(params[7+offset]);
|
||||
}
|
||||
|
||||
+10
-13
@@ -224,7 +224,7 @@ struct IRCDMessageChaninfo final
|
||||
bool created;
|
||||
Channel *c = Channel::FindOrCreate(params[0], created);
|
||||
|
||||
Anope::string modes = params[1];
|
||||
std::vector<Anope::string> modeparams;
|
||||
|
||||
if (params.size() == 3)
|
||||
{
|
||||
@@ -237,17 +237,17 @@ struct IRCDMessageChaninfo final
|
||||
switch(params[1][i])
|
||||
{
|
||||
case 'k':
|
||||
modes += " " + params[2];
|
||||
modeparams.push_back(params[2]);
|
||||
continue;
|
||||
case 'l':
|
||||
modes += " " + params[3];
|
||||
modeparams.push_back(params[3]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
c->ChangeTopicInternal(NULL, source.GetName(), params[4], Anope::CurTime);
|
||||
}
|
||||
|
||||
c->SetModesInternal(source, modes);
|
||||
c->SetModesInternal(source, params[1], modeparams);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -267,11 +267,13 @@ struct IRCDMessageJoin final
|
||||
User *user = source.GetUser();
|
||||
size_t pos = params[0].find('\7');
|
||||
Anope::string channel, modes;
|
||||
std::vector<Anope::string> modeparams;
|
||||
|
||||
if (pos != Anope::string::npos)
|
||||
{
|
||||
channel = params[0].substr(0, pos);
|
||||
modes = '+' + params[0].substr(pos+1, params[0].length()) + " " + user->nick;
|
||||
modes = '+' + params[0].substr(pos+1, params[0].length());
|
||||
modeparams.push_back(user->nick);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -287,7 +289,7 @@ struct IRCDMessageJoin final
|
||||
{
|
||||
Channel *c = Channel::Find(channel);
|
||||
if (c)
|
||||
c->SetModesInternal(source, modes);
|
||||
c->SetModesInternal(source, modes, modeparams);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -367,17 +369,12 @@ struct IRCDMessageMode final
|
||||
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
Anope::string modes = params[1];
|
||||
|
||||
for (size_t i = 2; i < params.size(); ++i)
|
||||
modes += " " + params[i];
|
||||
|
||||
if (IRCD->IsChannelValid(params[0]))
|
||||
{
|
||||
Channel *c = Channel::Find(params[0]);
|
||||
|
||||
if (c)
|
||||
c->SetModesInternal(source, modes);
|
||||
c->SetModesInternal(source, params[1], { params.begin() + 2, params.end() });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -485,7 +482,7 @@ struct IRCDMessageNJoin final
|
||||
users.push_back(sju);
|
||||
}
|
||||
|
||||
Message::Join::SJoin(source, params[0], 0, "", users);
|
||||
Message::Join::SJoin(source, params[0], 0, "", {}, users);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class RatboxProto final
|
||||
}
|
||||
|
||||
public:
|
||||
RatboxProto(Module *creator) : IRCDProto(creator, "Ratbox 3.0+")
|
||||
RatboxProto(Module *creator) : IRCDProto(creator, "ircd-ratbox 3+")
|
||||
{
|
||||
DefaultPseudoclientModes = "+oiS";
|
||||
CanSNLine = true;
|
||||
|
||||
+123
-127
@@ -14,7 +14,25 @@
|
||||
#include "modules/sasl.h"
|
||||
|
||||
typedef Anope::map<Anope::string> ModData;
|
||||
static Anope::string UplinkSID;
|
||||
|
||||
namespace
|
||||
{
|
||||
Anope::string UplinkSID;
|
||||
|
||||
bool IsExtBan(const Anope::string &str, Anope::string &name, Anope::string &value)
|
||||
{
|
||||
if (str[0] != '~')
|
||||
return false;
|
||||
|
||||
auto endpos = str.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1);
|
||||
if (endpos == Anope::string::npos || str[endpos] != ':' || endpos+1 == str.length())
|
||||
return false;
|
||||
|
||||
name = str.substr(1, endpos - 1);
|
||||
value = str.substr(endpos + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class UnrealIRCdProto final
|
||||
: public IRCDProto
|
||||
@@ -23,7 +41,10 @@ public:
|
||||
PrimitiveExtensibleItem<ModData> ClientModData;
|
||||
PrimitiveExtensibleItem<ModData> ChannelModData;
|
||||
|
||||
UnrealIRCdProto(Module *creator) : IRCDProto(creator, "UnrealIRCd 4+"), ClientModData(creator, "ClientModData"), ChannelModData(creator, "ChannelModData")
|
||||
UnrealIRCdProto(Module *creator)
|
||||
: IRCDProto(creator, "UnrealIRCd 6+")
|
||||
, ClientModData(creator, "ClientModData")
|
||||
, ChannelModData(creator, "ChannelModData")
|
||||
{
|
||||
DefaultPseudoclientModes = "+BioqS";
|
||||
CanSVSNick = true;
|
||||
@@ -216,21 +237,16 @@ private:
|
||||
|
||||
void SendConnect() override
|
||||
{
|
||||
/*
|
||||
NICKv2 = Nick Version 2
|
||||
VHP = Sends hidden host
|
||||
UMODE2 = sends UMODE2 on user modes
|
||||
NICKIP = Sends IP on NICK
|
||||
SJ3 = Supports SJOIN
|
||||
NOQUIT = No Quit
|
||||
TKLEXT = Extended TKL we don't use it but best to have it
|
||||
MLOCK = Supports the MLOCK server command
|
||||
VL = Version Info
|
||||
SID = SID/UID mode
|
||||
*/
|
||||
Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password);
|
||||
|
||||
Uplink::Send("PROTOCTL", "NICKv2", "VHP", "UMODE2", "NICKIP", "SJOIN", "SJOIN2", "SJ3", "NOQUIT", "TKLEXT", "MLOCK", "SID", "MTAGS", "BIGLINES");
|
||||
// BIGLINES: enable sending lines up to 16384 characters in length.
|
||||
// EAUTH: communicates information about the local server.
|
||||
// MLOCK: enable receiving the MLOCK message when a mode lock changes.
|
||||
// MTAGS: enable receiving IRCv3 message tags.
|
||||
// NEXTBANS: enables receiving named extended bans.
|
||||
// SID: communicates the unique identifier of the local server.
|
||||
// VHP: enable receiving the vhost in UID.
|
||||
Uplink::Send("PROTOCTL", "BIGLINES", "MLOCK", "MTAGS", "NEXTBANS", "VHP");
|
||||
Uplink::Send("PROTOCTL", "EAUTH=" + Me->GetName() + ",,,Anope-" + Anope::VersionShort());
|
||||
Uplink::Send("PROTOCTL", "SID=" + Me->GetSID());
|
||||
|
||||
@@ -348,16 +364,14 @@ private:
|
||||
|
||||
bool IsExtbanValid(const Anope::string &mask) override
|
||||
{
|
||||
return mask.length() >= 4 && mask[0] == '~' && mask[2] == ':';
|
||||
Anope::string name, value;
|
||||
return IsExtBan(mask, name, value);
|
||||
}
|
||||
|
||||
void SendLogin(User *u, NickAlias *na) override
|
||||
{
|
||||
/* 3.2.10.4+ treats users logged in with accounts as fully registered, even if -r, so we can not set this here. Just use the timestamp. */
|
||||
if (Servers::Capab.count("ESVID") > 0 && !na->nc->HasExt("UNCONFIRMED"))
|
||||
if (!na->nc->HasExt("UNCONFIRMED"))
|
||||
IRCD->SendMode(Config->GetClient("NickServ"), u, "+d", na->nc->display);
|
||||
else
|
||||
IRCD->SendMode(Config->GetClient("NickServ"), u, "+d", u->signon);
|
||||
}
|
||||
|
||||
void SendLogout(User *u) override
|
||||
@@ -448,54 +462,65 @@ private:
|
||||
|
||||
bool IsTagValid(const Anope::string &tname, const Anope::string &tvalue) override
|
||||
{
|
||||
if (Servers::Capab.count("MTAGS"))
|
||||
return true;
|
||||
return false;
|
||||
return !!Servers::Capab.count("MTAGS");
|
||||
}
|
||||
};
|
||||
|
||||
class UnrealExtBan
|
||||
: public ChannelModeVirtual<ChannelModeList>
|
||||
namespace UnrealExtBan
|
||||
{
|
||||
char ext;
|
||||
|
||||
public:
|
||||
UnrealExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual<ChannelModeList>(mname, basename)
|
||||
, ext(extban)
|
||||
class Base
|
||||
: public ChannelModeVirtual<ChannelModeList>
|
||||
{
|
||||
}
|
||||
private:
|
||||
char xbchar;
|
||||
Anope::string xbname;
|
||||
|
||||
ChannelMode *Wrap(Anope::string ¶m) override
|
||||
{
|
||||
param = "~" + Anope::string(ext) + ":" + param;
|
||||
return ChannelModeVirtual<ChannelModeList>::Wrap(param);
|
||||
}
|
||||
public:
|
||||
Base(const Anope::string &mname, const Anope::string& uname, char uchar)
|
||||
: ChannelModeVirtual<ChannelModeList>(mname, "BAN")
|
||||
, xbchar(uchar)
|
||||
, xbname(uname)
|
||||
{
|
||||
}
|
||||
|
||||
ChannelMode *Unwrap(ChannelMode *cm, Anope::string ¶m) override
|
||||
{
|
||||
if (cm->type != MODE_LIST || param.length() < 4 || param[0] != '~' || param[1] != ext || param[2] != ':')
|
||||
return cm;
|
||||
ChannelMode *Wrap(Anope::string ¶m) override
|
||||
{
|
||||
auto prefix = Servers::Capab.count("NEXTBANS") ? xbname : Anope::string(xbchar);
|
||||
param = Anope::printf("~%s:%s", prefix.c_str(), param.c_str());
|
||||
return ChannelModeVirtual<ChannelModeList>::Wrap(param);
|
||||
}
|
||||
|
||||
param = param.substr(3);
|
||||
return this;
|
||||
}
|
||||
};
|
||||
ChannelMode *Unwrap(ChannelMode *cm, Anope::string ¶m) override
|
||||
{
|
||||
// The mask must be in the format ~<letter>:<value> or ~<name>:<value>.
|
||||
if (cm->type != MODE_LIST)
|
||||
return cm;
|
||||
|
||||
Anope::string name, value;
|
||||
if (!IsExtBan(param, name, value))
|
||||
return cm;
|
||||
|
||||
if (name.length() == 1 ? name[0] != xbchar : name != xbname)
|
||||
return cm;
|
||||
|
||||
param = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
namespace UnrealExtban
|
||||
{
|
||||
class ChannelMatcher final
|
||||
: public UnrealExtBan
|
||||
: public Base
|
||||
{
|
||||
public:
|
||||
ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
ChannelMatcher()
|
||||
: Base("CHANNELBAN", "channel", 'c')
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string channel = mask.substr(3);
|
||||
|
||||
auto channel = e->GetMask();
|
||||
ChannelMode *cm = NULL;
|
||||
if (channel[0] != '#')
|
||||
{
|
||||
@@ -520,137 +545,113 @@ namespace UnrealExtban
|
||||
};
|
||||
|
||||
class EntryMatcher final
|
||||
: public UnrealExtBan
|
||||
: public Base
|
||||
{
|
||||
public:
|
||||
EntryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
EntryMatcher(const Anope::string &mname, const Anope::string &uname, char uchar)
|
||||
: Base(mname, uname, uchar)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
|
||||
return Entry(this->name, real_mask).Matches(u);
|
||||
return Entry(this->base, e->GetMask()).Matches(u);
|
||||
}
|
||||
};
|
||||
|
||||
class RealnameMatcher final
|
||||
: public UnrealExtBan
|
||||
: public Base
|
||||
{
|
||||
public:
|
||||
RealnameMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
RealnameMatcher()
|
||||
: Base("REALNAMEBAN", "realname", 'r')
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
|
||||
return Anope::Match(u->realname, real_mask);
|
||||
}
|
||||
};
|
||||
|
||||
class RegisteredMatcher final
|
||||
: public UnrealExtBan
|
||||
{
|
||||
public:
|
||||
RegisteredMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
return u->HasMode("REGISTERED") && mask.equals_ci(u->nick);
|
||||
return Anope::Match(u->realname, e->GetMask());
|
||||
}
|
||||
};
|
||||
|
||||
class AccountMatcher final
|
||||
: public UnrealExtBan
|
||||
: public Base
|
||||
{
|
||||
public:
|
||||
AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
AccountMatcher()
|
||||
: Base("ACCOUNTBAN", "account", 'a')
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
|
||||
if (real_mask == "0" && !u->Account()) /* ~a:0 is special and matches all unauthenticated users */
|
||||
if (e->GetMask() == "0" && !u->Account()) /* ~a:0 is special and matches all unauthenticated users */
|
||||
return true;
|
||||
|
||||
return u->Account() && Anope::Match(u->Account()->display, real_mask);
|
||||
return u->IsIdentified() && Anope::Match(u->Account()->display, e->GetMask());
|
||||
}
|
||||
};
|
||||
|
||||
class FingerprintMatcher final
|
||||
: public UnrealExtBan
|
||||
: public Base
|
||||
{
|
||||
public:
|
||||
FingerprintMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
FingerprintMatcher()
|
||||
: Base("SSLBAN", "certfp", 'S')
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
return !u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask);
|
||||
return !u->fingerprint.empty() && Anope::Match(u->fingerprint, e->GetMask());
|
||||
}
|
||||
};
|
||||
|
||||
class OperclassMatcher final
|
||||
: public UnrealExtBan
|
||||
: public Base
|
||||
{
|
||||
public:
|
||||
OperclassMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
OperclassMatcher()
|
||||
: Base("OPERCLASSBAN", "operclass", 'O')
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
ModData *moddata = u->GetExt<ModData>("ClientModData");
|
||||
return moddata != NULL && moddata->find("operclass") != moddata->end() && Anope::Match((*moddata)["operclass"], real_mask);
|
||||
return moddata != NULL && moddata->find("operclass") != moddata->end() && Anope::Match((*moddata)["operclass"], e->GetMask());
|
||||
}
|
||||
};
|
||||
|
||||
class TimedBanMatcher final
|
||||
: public UnrealExtBan
|
||||
: public Base
|
||||
{
|
||||
public:
|
||||
TimedBanMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
TimedBanMatcher()
|
||||
: Base("TIMEDBAN", "time", 't')
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
/* strip down the time (~t:1234:) and call other matchers */
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
auto real_mask = e->GetMask();
|
||||
real_mask = real_mask.substr(real_mask.find(":") + 1);
|
||||
return Entry("BAN", real_mask).Matches(u);
|
||||
}
|
||||
};
|
||||
|
||||
class CountryMatcher final
|
||||
: public UnrealExtBan
|
||||
: public Base
|
||||
{
|
||||
public:
|
||||
CountryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
CountryMatcher()
|
||||
: Base("COUNTRYBAN", "country", 'C')
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
ModData *moddata = u->GetExt<ModData>("ClientModData");
|
||||
if (moddata == NULL || moddata->find("geoip") == moddata->end())
|
||||
return false;
|
||||
@@ -660,7 +661,7 @@ namespace UnrealExtban
|
||||
while (sep.GetToken(tokenbuf))
|
||||
{
|
||||
if (tokenbuf.rfind("cc=", 0) == 0)
|
||||
return (tokenbuf.substr(3, 2) == real_mask);
|
||||
return (tokenbuf.substr(3, 2) == e->GetMask());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -846,17 +847,16 @@ struct IRCDMessageCapab final
|
||||
case 'b':
|
||||
ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b'));
|
||||
|
||||
ModeManager::AddChannelMode(new UnrealExtban::ChannelMatcher("CHANNELBAN", "BAN", 'c'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("JOINBAN", "BAN", 'j'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("NONICKBAN", "BAN", 'n'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("QUIET", "BAN", 'q'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::RealnameMatcher("REALNAMEBAN", "BAN", 'r'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::RegisteredMatcher("REGISTEREDBAN", "BAN", 'R'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::AccountMatcher("ACCOUNTBAN", "BAN", 'a'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::FingerprintMatcher("SSLBAN", "BAN", 'S'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::TimedBanMatcher("TIMEDBAN", "BAN", 't'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::OperclassMatcher("OPERCLASSBAN", "BAN", 'O'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::CountryMatcher("COUNTRYBAN", "BAN", 'C'));
|
||||
ModeManager::AddChannelMode(new UnrealExtBan::ChannelMatcher());
|
||||
ModeManager::AddChannelMode(new UnrealExtBan::EntryMatcher("JOINBAN", "join", 'j'));
|
||||
ModeManager::AddChannelMode(new UnrealExtBan::EntryMatcher("NONICKBAN", "nickchange", 'n'));
|
||||
ModeManager::AddChannelMode(new UnrealExtBan::EntryMatcher("QUIET", "quiet", 'q'));
|
||||
ModeManager::AddChannelMode(new UnrealExtBan::RealnameMatcher());
|
||||
ModeManager::AddChannelMode(new UnrealExtBan::AccountMatcher());
|
||||
ModeManager::AddChannelMode(new UnrealExtBan::FingerprintMatcher());
|
||||
ModeManager::AddChannelMode(new UnrealExtBan::TimedBanMatcher());
|
||||
ModeManager::AddChannelMode(new UnrealExtBan::OperclassMatcher());
|
||||
ModeManager::AddChannelMode(new UnrealExtBan::CountryMatcher());
|
||||
continue;
|
||||
case 'e':
|
||||
ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e'));
|
||||
@@ -1155,10 +1155,7 @@ struct IRCDMessageMode final
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
auto final_is_ts = server_ts && source.GetServer() != NULL;
|
||||
|
||||
Anope::string modes = params[1];
|
||||
for (unsigned i = 2; i < params.size() - (final_is_ts ? 1 : 0); ++i)
|
||||
modes += " " + params[i];
|
||||
auto last_param = params.end() - (params.size() > 3 && final_is_ts ? 1 : 0);
|
||||
|
||||
if (IRCD->IsChannelValid(params[0]))
|
||||
{
|
||||
@@ -1166,7 +1163,7 @@ struct IRCDMessageMode final
|
||||
auto ts = final_is_ts ? IRCD->ExtractTimestamp(params.back()) : 0;
|
||||
|
||||
if (c)
|
||||
c->SetModesInternal(source, modes, ts);
|
||||
c->SetModesInternal(source, params[1], { params.begin() + 2, last_param }, ts);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1428,11 +1425,12 @@ struct IRCDMessageSJoin final
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
Anope::string modes;
|
||||
std::vector<Anope::string> modeparams;
|
||||
if (params.size() >= 4)
|
||||
for (unsigned i = 2; i < params.size() - 1; ++i)
|
||||
modes += " " + params[i];
|
||||
if (!modes.empty())
|
||||
modes.erase(modes.begin());
|
||||
{
|
||||
modes = params[2];
|
||||
modeparams = { params.begin() + 3, params.end() };
|
||||
}
|
||||
|
||||
std::list<Anope::string> bans, excepts, invites;
|
||||
std::list<Message::Join::SJoinUser> users;
|
||||
@@ -1482,7 +1480,7 @@ struct IRCDMessageSJoin final
|
||||
}
|
||||
|
||||
auto ts = IRCD->ExtractTimestamp(params[0]);
|
||||
Message::Join::SJoin(source, params[1], ts, modes, users);
|
||||
Message::Join::SJoin(source, params[1], ts, modes, modeparams, users);
|
||||
|
||||
if (!bans.empty() || !excepts.empty() || !invites.empty())
|
||||
{
|
||||
@@ -1753,8 +1751,6 @@ public:
|
||||
void OnUserNickChange(User *u, const Anope::string &) override
|
||||
{
|
||||
u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED"));
|
||||
if (Servers::Capab.count("ESVID") == 0)
|
||||
IRCD->SendLogout(u);
|
||||
}
|
||||
|
||||
void OnChannelSync(Channel *c) override
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
{
|
||||
SQLOperResultDeleter d(this);
|
||||
|
||||
if (!user || !user->Account())
|
||||
if (!user || !user->IsIdentified())
|
||||
return;
|
||||
|
||||
if (r.Rows() == 0)
|
||||
|
||||
@@ -226,7 +226,7 @@ private:
|
||||
request.reply("ip", u->ip.addr());
|
||||
request.reply("timestamp", Anope::ToString(u->timestamp));
|
||||
request.reply("signon", Anope::ToString(u->signon));
|
||||
if (u->Account())
|
||||
if (u->IsIdentified())
|
||||
{
|
||||
request.reply("account", iface->Sanitize(u->Account()->display));
|
||||
if (u->Account()->o)
|
||||
|
||||
+22
-4
@@ -20,7 +20,11 @@
|
||||
|
||||
Serialize::Checker<botinfo_map> BotListByNick("BotInfo"), BotListByUID("BotInfo");
|
||||
|
||||
BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes) : User(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", IRCD ? IRCD->UID_Retrieve() : "", NULL), Serializable("BotInfo"), channels("ChannelInfo"), botmodes(bmodes)
|
||||
BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes)
|
||||
: User(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", {}, IRCD ? IRCD->UID_Retrieve() : "", NULL)
|
||||
, Serializable("BotInfo")
|
||||
, channels("ChannelInfo")
|
||||
, botmodes(bmodes)
|
||||
{
|
||||
this->lastmsg = this->created = Anope::CurTime;
|
||||
this->introduced = false;
|
||||
@@ -35,9 +39,16 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A
|
||||
// If we're synchronised with the uplink already, send the bot.
|
||||
if (Me && Me->IsSynced())
|
||||
{
|
||||
Anope::string tmodes = !this->botmodes.empty() ? ("+" + this->botmodes) : IRCD->DefaultPseudoclientModes;
|
||||
if (!tmodes.empty())
|
||||
this->SetModesInternal(this, tmodes);
|
||||
spacesepstream modesep(this->botmodes.empty() ? IRCD->DefaultPseudoclientModes : "+" + this->botmodes);
|
||||
|
||||
Anope::string modechars;
|
||||
modesep.GetToken(modechars);
|
||||
|
||||
std::vector<Anope::string> modeparams;
|
||||
modesep.GetTokens(modeparams);
|
||||
|
||||
if (!modechars.empty())
|
||||
this->SetModesInternal(this, modechars, modeparams);
|
||||
|
||||
XLine x(this->nick, "Reserved for services");
|
||||
IRCD->SendSQLine(NULL, &x);
|
||||
@@ -254,6 +265,13 @@ CommandInfo *BotInfo::GetCommand(const Anope::string &cname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Anope::string BotInfo::GetQueryCommand() const
|
||||
{
|
||||
if (Config->ServiceAlias && !this->alias.empty())
|
||||
return Anope::printf("/%s", this->alias.c_str());
|
||||
return Anope::printf("/msg %s", this->nick.c_str());
|
||||
}
|
||||
|
||||
BotInfo *BotInfo::Find(const Anope::string &nick, bool nick_only)
|
||||
{
|
||||
if (!nick_only && IRCD != NULL && IRCD->RequiresID)
|
||||
|
||||
+13
-15
@@ -611,13 +611,13 @@ void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const Anope::string &cmo
|
||||
}
|
||||
}
|
||||
|
||||
void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts, bool enforce_mlock)
|
||||
void Channel::SetModesInternal(MessageSource &source, const Anope::string &modes, const std::vector<Anope::string> ¶ms, time_t ts, bool enforce_mlock)
|
||||
{
|
||||
if (!ts)
|
||||
;
|
||||
else if (ts > this->creation_time)
|
||||
{
|
||||
Log(LOG_DEBUG) << "Dropping mode " << mode << " on " << this->name << ", " << ts << " > " << this->creation_time;
|
||||
Log(LOG_DEBUG) << "Dropping mode " << modes << " on " << this->name << ", " << ts << " > " << this->creation_time;
|
||||
return;
|
||||
}
|
||||
else if (ts < this->creation_time)
|
||||
@@ -631,20 +631,18 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
|
||||
/* Removing channel modes *may* delete this channel */
|
||||
Reference<Channel> this_reference(this);
|
||||
|
||||
spacesepstream sep_modes(mode);
|
||||
Anope::string m;
|
||||
|
||||
sep_modes.GetToken(m);
|
||||
|
||||
Anope::string modestring;
|
||||
Anope::string paramstring;
|
||||
int add = -1;
|
||||
bool changed = false;
|
||||
for (unsigned int i = 0, end = m.length(); i < end && this_reference; ++i)
|
||||
auto paramit = params.begin();
|
||||
for (const auto mchar : modes)
|
||||
{
|
||||
ChannelMode *cm;
|
||||
if (!this_reference)
|
||||
break;
|
||||
|
||||
switch (m[i])
|
||||
ChannelMode *cm;
|
||||
switch (mchar)
|
||||
{
|
||||
case '+':
|
||||
modestring += '+';
|
||||
@@ -657,10 +655,10 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
|
||||
default:
|
||||
if (add == -1)
|
||||
continue;
|
||||
cm = ModeManager::FindChannelModeByChar(m[i]);
|
||||
cm = ModeManager::FindChannelModeByChar(mchar);
|
||||
if (!cm)
|
||||
{
|
||||
Log(LOG_DEBUG) << "Channel::SetModeInternal: Unknown mode char " << m[i];
|
||||
Log(LOG_DEBUG) << "Channel::SetModeInternal: Unknown mode char " << mchar;
|
||||
continue;
|
||||
}
|
||||
modestring += cm->mchar;
|
||||
@@ -686,9 +684,9 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Anope::string token;
|
||||
if (sep_modes.GetToken(token))
|
||||
if (paramit != params.end())
|
||||
{
|
||||
auto token = *paramit++;
|
||||
User *u = NULL;
|
||||
if (cm->type == MODE_STATUS && (u = User::Find(token)))
|
||||
paramstring += " " + u->nick;
|
||||
@@ -703,7 +701,7 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
|
||||
this->RemoveModeInternal(source, cm, token, enforce_mlock);
|
||||
}
|
||||
else
|
||||
Log() << "warning: Channel::SetModesInternal() received more modes requiring params than params, modes: " << mode;
|
||||
Log() << "warning: Channel::SetModesInternal() received more modes requiring params than params, modes: " << modes;
|
||||
}
|
||||
|
||||
if (!this_reference)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user