mirror of
https://github.com/anope/anope.git
synced 2026-06-12 17:24:49 +02:00
Banish irc2sql to the shadow realm.
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
# 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)
|
||||
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)
|
||||
install(FILES ${DATA}
|
||||
DESTINATION ${CONF_DIR}
|
||||
)
|
||||
|
||||
@@ -1414,23 +1414,3 @@ include
|
||||
type = "file"
|
||||
name = "chanstats.example.conf"
|
||||
}
|
||||
|
||||
/*
|
||||
* [DEPRECATED] IRC2SQL Gateway
|
||||
*
|
||||
* This module collects data about users, channels and servers. It doesn't build stats
|
||||
* itself, however, it gives you the database, it's up to you how you use it.
|
||||
*
|
||||
* This module is deprecated in favour of the RPC interface and the rpc_data
|
||||
* module. This should provide almost all of the same information as irc2sql but
|
||||
* without requiring MySQL and with much better performance. If you have a use
|
||||
* case which is not covered by rpc_data then please open an issue so we can
|
||||
* extend rpc_data before irc2sql is removed.
|
||||
*
|
||||
* Requires a MySQL Database and MySQL version 5.5 or higher
|
||||
*/
|
||||
#include
|
||||
{
|
||||
type = "file"
|
||||
name = "irc2sql.example.conf"
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Example configuration file for the irc2sql gateway
|
||||
*
|
||||
*/
|
||||
|
||||
service
|
||||
{
|
||||
/*
|
||||
* The name of the StatServ client.
|
||||
*/
|
||||
nick = "StatServ"
|
||||
|
||||
/*
|
||||
* The username of the StatServ client.
|
||||
*/
|
||||
user = "StatServ"
|
||||
|
||||
/*
|
||||
* The hostname of the StatServ client.
|
||||
*/
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the StatServ client.
|
||||
*/
|
||||
real = "Statistical Service"
|
||||
|
||||
/*
|
||||
* The modes this client should use.
|
||||
* Do not modify this unless you know what you are doing.
|
||||
*
|
||||
* These modes are very IRCd specific. If left commented, sane defaults
|
||||
* are used based on what protocol module you have loaded.
|
||||
*
|
||||
* Note that setting this option incorrectly could potentially BREAK some, if
|
||||
* not all, usefulness of the client. We will not support you if this client is
|
||||
* unable to do certain things if this option is enabled.
|
||||
*/
|
||||
#modes = "+o"
|
||||
|
||||
/*
|
||||
* An optional comma separated list of channels this service should join. Outside
|
||||
* of log channels this is not very useful, as the service will just idle in the
|
||||
* specified channels, and will not accept any types of commands.
|
||||
*
|
||||
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
|
||||
*/
|
||||
#channels = "@#stats,#mychan"
|
||||
}
|
||||
|
||||
module
|
||||
{
|
||||
name = "irc2sql"
|
||||
|
||||
/*
|
||||
* The name of the client that should send the CTCP VERSION requests.
|
||||
* It must already exist or must be defined in the following service block.
|
||||
*/
|
||||
client = "StatServ"
|
||||
|
||||
/*
|
||||
* The name of the SQL engine to use.
|
||||
* This must be MySQL and must match the name in the mysql{} block
|
||||
*/
|
||||
engine = "mysql/main"
|
||||
|
||||
/*
|
||||
* An optional prefix to prepended to the name of each created table.
|
||||
* Do not use the same prefix for other programs.
|
||||
*/
|
||||
prefix = "anope_"
|
||||
|
||||
/*
|
||||
* GeoIP - Automatically adds users geoip location to the user table.
|
||||
* Tables are created by irc2sql, you have to run the
|
||||
* geoipupdate script after you started Anope to download
|
||||
* and import the GeoIP database.
|
||||
*
|
||||
* The geoip database can be the smaller "country" database or the
|
||||
* larger "city" database. Comment to disable geoip lookup.
|
||||
*/
|
||||
geoip_database = "country"
|
||||
|
||||
/*
|
||||
* Get the CTCP version from users
|
||||
* The users connecting to the network will receive a CTCP VERSION
|
||||
* request from the above configured stats client
|
||||
*/
|
||||
ctcpuser = "yes"
|
||||
|
||||
/*
|
||||
* Send out CTCP VERSION requests to users during burst.
|
||||
* Disable this if you restart Anope often and don't want to
|
||||
* annoy your users.
|
||||
*/
|
||||
ctcpeob = "yes"
|
||||
}
|
||||
@@ -1,514 +0,0 @@
|
||||
/*
|
||||
* Example configuration file for Anope. After making the appropriate
|
||||
* changes to this file, place it in the Anope conf directory (as
|
||||
* specified in the "Config" script, default /home/username/anope/conf)
|
||||
* under the name "anope.conf".
|
||||
*
|
||||
* The format of this file is fairly simple: three types of comments are supported:
|
||||
* - All text after a '#' on a line is ignored, as in shell scripting
|
||||
* - All text after '//' on a line is ignored, as in C++
|
||||
* - A block of text like this one is ignored, as in C
|
||||
*
|
||||
* Outside of comments, there are three structures: blocks, keys, and values.
|
||||
*
|
||||
* A block is a named container, which contains a number of key to value pairs
|
||||
* - you may think of this as an array.
|
||||
*
|
||||
* A block is created like so:
|
||||
* foobar
|
||||
* {
|
||||
* moo = "cow"
|
||||
* foo = bar
|
||||
* }
|
||||
*
|
||||
* Note that nameless blocks are allowed and are often used with comments to allow
|
||||
* easily commenting an entire block, for example:
|
||||
* #foobar
|
||||
* {
|
||||
* moo = "cow"
|
||||
* foo = bar
|
||||
* }
|
||||
* is an entirely commented block.
|
||||
*
|
||||
* Keys are case insensitive. Values depend on what key - generally, information is
|
||||
* given in the key comment. The quoting of values (and most other syntax) is quite
|
||||
* flexible, however, please do not forget to quote your strings:
|
||||
*
|
||||
* "This is a parameter string with spaces in it"
|
||||
*
|
||||
* If you need to include a double quote inside a quoted string, precede it
|
||||
* by a backslash:
|
||||
*
|
||||
* "This string has \"double quotes\" in it"
|
||||
*
|
||||
* Time parameters can be specified either as an integer representing a
|
||||
* number of seconds (e.g. "3600" = 1 hour), or as an integer with a unit
|
||||
* specifier: "s" = seconds, "m" = minutes, "h" = hours, "d" = days.
|
||||
* Combinations (such as "1h30m") are not permitted. Examples (all of which
|
||||
* represent the same length of time, one day):
|
||||
*
|
||||
* "86400", "86400s", "1440m", "24h", "1d"
|
||||
*
|
||||
* In the documentation for each directive, one of the following will be
|
||||
* included to indicate whether an option is required:
|
||||
*
|
||||
* [REQUIRED]
|
||||
* Indicates a directive which must be given. Without it, Anope will
|
||||
* not start.
|
||||
*
|
||||
* [RECOMMENDED]
|
||||
* Indicates a directive which may be omitted, but omitting it may cause
|
||||
* undesirable side effects.
|
||||
*
|
||||
* [OPTIONAL]
|
||||
* Indicates a directive which is optional. If not given, the feature
|
||||
* will typically be disabled. If this is not the case, more
|
||||
* information will be given in the documentation.
|
||||
*
|
||||
* [DISCOURAGED]
|
||||
* Indicates a directive which may cause undesirable side effects if
|
||||
* specified.
|
||||
*
|
||||
* [DEPRECATED]
|
||||
* Indicates a directive which will disappear in a future version of
|
||||
* Anope, usually because its functionality has been either
|
||||
* superseded by that of other directives or incorporated into the main
|
||||
* program.
|
||||
*/
|
||||
|
||||
/*
|
||||
* [OPTIONAL] Defines
|
||||
*
|
||||
* You can use defines for repeated information, which can be used to easily change many
|
||||
* values in the configuration at once.
|
||||
*
|
||||
* To use a define called foo.bar you use ${foo.bar} in your config file. You can also use
|
||||
* environment variables by prefixing their name with "env." like ${env.USER}.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The services.host define is used in multiple different locations throughout the
|
||||
* configuration for the server name and pseudoclient hostnames.
|
||||
*/
|
||||
define
|
||||
{
|
||||
name = "services.host"
|
||||
value = "stats.example.com"
|
||||
}
|
||||
|
||||
/*
|
||||
* [OPTIONAL] Additional Includes
|
||||
*
|
||||
* You can include additional configuration files here.
|
||||
* You may also include executable files, which will be executed and
|
||||
* the output from it will be included into your configuration.
|
||||
*/
|
||||
|
||||
#include
|
||||
{
|
||||
type = "file"
|
||||
name = "some.conf"
|
||||
}
|
||||
|
||||
#include
|
||||
{
|
||||
type = "executable"
|
||||
name = "/usr/bin/wget -q -O - https://some.misconfigured.network.com/stats.conf"
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] IRCd Config
|
||||
*
|
||||
* This section is used to set up Anope to connect to your IRC network.
|
||||
* This section can be included multiple times, and Anope will attempt to
|
||||
* connect to each server until it finally connects.
|
||||
*
|
||||
* Each uplink IRCd should have a corresponding configuration to allow Anope
|
||||
* to link to it.
|
||||
*
|
||||
* An example configuration for InspIRCd that is compatible with the below uplink
|
||||
* and serverinfo configuration would look like:
|
||||
*
|
||||
* # This goes in inspircd.conf, *NOT* your Anope config!
|
||||
* <link name="stats.example.com"
|
||||
* ipaddr="127.0.0.1"
|
||||
* port="7000"
|
||||
* sendpass="mypassword"
|
||||
* recvpass="mypassword">
|
||||
* <uline server="stats.example.com" silent="yes">
|
||||
* <bind address="127.0.0.1" port="7000" type="servers">
|
||||
*
|
||||
* An example configuration for UnrealIRCd that is compatible with the below uplink
|
||||
* and serverinfo configuration would look like:
|
||||
*
|
||||
* // This goes in unrealircd.conf, *NOT* your Anope config!
|
||||
* listen {
|
||||
* ip 127.0.0.1;
|
||||
* port 7000;
|
||||
* options {
|
||||
* serversonly;
|
||||
* };
|
||||
* };
|
||||
* link stats.example.com {
|
||||
* incoming {
|
||||
* mask *@127.0.0.1;
|
||||
* };
|
||||
* password "mypassword";
|
||||
* class servers;
|
||||
* };
|
||||
* ulines { stats.example.com; };
|
||||
*/
|
||||
uplink
|
||||
{
|
||||
/*
|
||||
* The IP address, hostname, or UNIX socket path of the IRC server you wish
|
||||
* to connect Anope to.
|
||||
* Usually, you will want to connect over 127.0.0.1 (aka localhost).
|
||||
*
|
||||
* NOTE: On some shell providers, this will not be an option.
|
||||
*/
|
||||
host = "127.0.0.1"
|
||||
|
||||
/*
|
||||
* The protocol that Anope should use when connecting to the uplink. Can
|
||||
* be set to "ipv4" (the default), "ipv6", or "unix".
|
||||
*/
|
||||
protocol = "ipv4"
|
||||
|
||||
/*
|
||||
* Enable if Anope should connect using SSL.
|
||||
* You must have an SSL module loaded for this to work.
|
||||
*/
|
||||
ssl = no
|
||||
|
||||
/*
|
||||
* The port to connect to.
|
||||
* The IRCd *MUST* be configured to listen on this port, and to accept
|
||||
* server connections.
|
||||
*
|
||||
* Refer to your IRCd documentation for how this is to be done.
|
||||
*/
|
||||
port = 7000
|
||||
|
||||
/*
|
||||
* The password to send to the IRC server for authentication.
|
||||
* This must match the link block on your IRCd.
|
||||
*
|
||||
* Refer to your IRCd documentation for more information on link blocks.
|
||||
*/
|
||||
password = "mypassword"
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] Server Information
|
||||
*
|
||||
* This section contains information about the services server.
|
||||
*/
|
||||
serverinfo
|
||||
{
|
||||
/*
|
||||
* The hostname that Anope will be seen as, it must have no conflicts with any
|
||||
* other server names on the rest of your IRC network. Note that it does not have
|
||||
* to be an existing hostname, just one that isn't on your network already.
|
||||
*/
|
||||
name = "${services.host}"
|
||||
|
||||
/*
|
||||
* The text which should appear as the server's information in /WHOIS and similar
|
||||
* queries.
|
||||
*/
|
||||
description = "Anope IRC Statistics"
|
||||
|
||||
/*
|
||||
* The local address that Anope will bind to before connecting to the remote
|
||||
* server. This may be useful for multihomed hosts. If omitted, Anope will let
|
||||
* the Operating System choose the local address. This directive is optional.
|
||||
*
|
||||
* If you don't know what this means or don't need to use it, just leave this
|
||||
* directive commented out.
|
||||
*/
|
||||
#localhost = "nowhere."
|
||||
|
||||
/*
|
||||
* What Server ID to use for this connection?
|
||||
* Note: This should *ONLY* be used for TS6/P10 IRCds. Refer to your IRCd documentation
|
||||
* to see if this is needed.
|
||||
*/
|
||||
#id = "00A"
|
||||
|
||||
/*
|
||||
* The filename containing the Anope process ID. The path is relative to the
|
||||
* data directory.
|
||||
*/
|
||||
pid = "anope.pid"
|
||||
|
||||
/*
|
||||
* The filename containing the Message of the Day. The path is relative to the
|
||||
* config directory.
|
||||
*/
|
||||
motd = "motd.txt"
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] Protocol module
|
||||
*
|
||||
* This directive tells Anope which IRCd Protocol to speak when connecting.
|
||||
* You MUST modify this to match the IRCd you run.
|
||||
*
|
||||
* Supported:
|
||||
* - hybrid
|
||||
* - inspircd
|
||||
* - ngircd
|
||||
* - plexus
|
||||
* - ratbox
|
||||
* - solanum
|
||||
* - unrealircd
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "inspircd"
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] Network Information
|
||||
*
|
||||
* This section contains information about the IRC network that Anope will be
|
||||
* connecting to.
|
||||
*/
|
||||
networkinfo
|
||||
{
|
||||
/*
|
||||
* This is the name of the network that Anope will be running on.
|
||||
*/
|
||||
networkname = "LocalNet"
|
||||
|
||||
/*
|
||||
* Set this to the maximum allowed nick length on your network.
|
||||
* Be sure to set this correctly, as setting this wrong can result in
|
||||
* Anope being disconnected from the network. Defaults to 31.
|
||||
*/
|
||||
#nicklen = 31
|
||||
|
||||
/* Set this to the maximum allowed ident length on your network.
|
||||
* Be sure to set this correctly, as setting this wrong can result in
|
||||
* Anope being disconnected from the network. Defaults to 10.
|
||||
*/
|
||||
#userlen = 10
|
||||
|
||||
/* Set this to the maximum allowed hostname length on your network.
|
||||
* Be sure to set this correctly, as setting this wrong can result in
|
||||
* Anope being disconnected from the network. Defaults to 64.
|
||||
*/
|
||||
#hostlen = 64
|
||||
|
||||
/* Set this to the maximum allowed channel length on your network.
|
||||
* Defaults to 64.
|
||||
*/
|
||||
#chanlen = 32
|
||||
|
||||
/* The maximum number of list modes settable on a channel (such as b, e, I).
|
||||
* Comment out or set to 0 to disable.
|
||||
*/
|
||||
modelistsize = 100
|
||||
|
||||
/*
|
||||
* The characters allowed in hostnames. This is used for validating hostnames given
|
||||
* to services, such as BotServ bot hostnames and user vhosts. Changing this is not
|
||||
* recommended unless you know for sure your IRCd supports whatever characters you are
|
||||
* wanting to use. Telling services to set a vhost containing characters your IRCd
|
||||
* disallows could potentially break the IRCd and/or Anope.
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
*/
|
||||
vhost_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-"
|
||||
|
||||
/*
|
||||
* If enabled, allows vhosts to not contain dots (.).
|
||||
* Newer IRCds generally do not have a problem with this, but the same warning as
|
||||
* vhost_chars applies.
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
*/
|
||||
allow_undotted_vhosts = no
|
||||
|
||||
/*
|
||||
* The characters that are not allowed to be at the very beginning or very ending
|
||||
* of a vhost. The same warning as vhost_chars applies.
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
*/
|
||||
disallow_start_or_end = ".-"
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] Anope Options
|
||||
*
|
||||
* This section contains various options which determine how Anope will operate.
|
||||
*/
|
||||
options
|
||||
{
|
||||
/*
|
||||
* On Linux/UNIX systems Anope can setuid and setgid to this user and group
|
||||
* after starting up. This is useful if Anope has to bind to privileged ports.
|
||||
*/
|
||||
#user = "anope"
|
||||
#group = "anope"
|
||||
|
||||
/*
|
||||
* The case mapping used by services. This must be set to a valid locale name
|
||||
* installed on your machine. Anope uses this case map to compare, with
|
||||
* case insensitivity, things such as nick names, channel names, etc.
|
||||
*
|
||||
* We provide two special casemaps shipped with Anope, ascii and rfc1459.
|
||||
*
|
||||
* This value should be set to what your IRCd uses, which is probably rfc1459,
|
||||
* however Anope has always used ascii for comparison, so the default is ascii.
|
||||
*
|
||||
* Changing this value once set is not recommended.
|
||||
*/
|
||||
casemap = "ascii"
|
||||
|
||||
/*
|
||||
* Sets the timeout period for reading from the uplink.
|
||||
*/
|
||||
readtimeout = 5s
|
||||
|
||||
/*
|
||||
* If set, Anope will only show /stats o to IRC Operators. This directive
|
||||
* is optional.
|
||||
*/
|
||||
#hidestatso = yes
|
||||
|
||||
/*
|
||||
* A space-separated list of U-lined servers on your network, it is assumed that
|
||||
* the servers in this list are allowed to set channel modes and Anope will
|
||||
* not attempt to reverse their mode changes.
|
||||
*
|
||||
* WARNING: Do NOT put your normal IRC user servers in this directive.
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
#ulineservers = "services.your.network"
|
||||
|
||||
/*
|
||||
* How long to wait between connection retries with the uplink(s).
|
||||
*/
|
||||
retrywait = 60s
|
||||
}
|
||||
|
||||
/*
|
||||
* [RECOMMENDED] Logging Configuration
|
||||
*
|
||||
* This section is used for configuring what is logged and where it is logged to.
|
||||
* You may have multiple log blocks if you wish. Remember to properly secure any
|
||||
* channels you choose to have Anope log to!
|
||||
*/
|
||||
log
|
||||
{
|
||||
/*
|
||||
* Target(s) to log to, which may be one of the following:
|
||||
* - a channel name
|
||||
* - a filename
|
||||
* - globops
|
||||
*/
|
||||
target = "stats.log"
|
||||
|
||||
/* Log to both stats.log and the channel #stats
|
||||
*
|
||||
* Note that some older IRCds, such as Ratbox, require services to be in the
|
||||
* log channel to be able to message it. To do this, configure service:channels to
|
||||
* join your logging channel.
|
||||
*/
|
||||
#target = "stats.log #stats"
|
||||
|
||||
/*
|
||||
* The source(s) to only accept log messages from. Leave commented to allow all sources.
|
||||
* This can be a users name, a channel name, one of our clients (e.g. OperServ), or a server name.
|
||||
*/
|
||||
#source = ""
|
||||
|
||||
/*
|
||||
* The bot used to log generic messages which have no predefined sender if there
|
||||
* is a channel in the target directive.
|
||||
*/
|
||||
bot = "Global"
|
||||
|
||||
/*
|
||||
* The number of days to keep log files, only useful if you are logging to a file.
|
||||
* Set to 0 to never delete old log files.
|
||||
*
|
||||
* Note that Anope must run 24 hours a day for this feature to work correctly.
|
||||
*/
|
||||
logage = 7
|
||||
|
||||
/*
|
||||
* What types of log messages should be logged by this block. There are nine general categories:
|
||||
*
|
||||
* servers - Server actions, linking, squitting, etc.
|
||||
* channels - Actions in channels such as joins, parts, kicks, etc.
|
||||
* users - User actions such as connecting, disconnecting, changing name, etc.
|
||||
* other - All other messages without a category.
|
||||
* rawio - Logs raw input and output from services
|
||||
* debug - Debug messages (log files can become VERY large from this).
|
||||
*
|
||||
* These options determine what messages from the categories should be logged. Wildcards are accepted, and
|
||||
* you can also negate values with a ~. For example, "~operserv/akill operserv/*" would log all operserv
|
||||
* messages except for operserv/akill. Note that processing stops at the first matching option, which
|
||||
* means "* ~operserv/*" would log everything because * matches everything.
|
||||
*
|
||||
* Valid server options are:
|
||||
* connect, quit, sync, squit
|
||||
*
|
||||
* Valid channel options are:
|
||||
* create, destroy, join, part, kick, leave, mode
|
||||
*
|
||||
* Valid user options are:
|
||||
* connect, disconnect, quit, nick, ident, host, mode, maxusers, oper, away
|
||||
*
|
||||
* Rawio and debug are simple yes/no answers, there are no types for them.
|
||||
*
|
||||
* Note that modules may add their own values to these options.
|
||||
*/
|
||||
servers = "*"
|
||||
#channels = "~mode *"
|
||||
users = "connect disconnect nick"
|
||||
other = "*"
|
||||
rawio = no
|
||||
debug = no
|
||||
}
|
||||
|
||||
/*
|
||||
* [REQUIRED] MySQL Database configuration.
|
||||
*
|
||||
* mysql
|
||||
*
|
||||
* This module allows other modules to use MySQL.
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "mysql"
|
||||
|
||||
mysql
|
||||
{
|
||||
/* The name of this service. */
|
||||
name = "mysql/main"
|
||||
database = "anope"
|
||||
server = "127.0.0.1"
|
||||
username = "anope"
|
||||
password = "mypassword"
|
||||
port = 3306
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* IRC2SQL Gateway
|
||||
* This module collects data about users, channels and servers. It doesn't build stats
|
||||
* itself, however, it gives you the database, it's up to you how you use it.
|
||||
*
|
||||
* Requires a MySQL Database and MySQL version 5.5 or higher
|
||||
*/
|
||||
include
|
||||
{
|
||||
type = "file"
|
||||
name = "irc2sql.example.conf"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
build_subdir(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -1,325 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2013-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#include "irc2sql.h"
|
||||
|
||||
void IRC2SQL::OnShutdown()
|
||||
{
|
||||
// TODO: test if we really have to use blocking query here
|
||||
// (sometimes mysql get unloaded before the other thread executed all queries)
|
||||
if (this->sql)
|
||||
SQL::Result r = this->sql->RunQuery(SQL::Query("CALL " + prefix + "OnShutdown()"));
|
||||
quitting = true;
|
||||
}
|
||||
|
||||
void IRC2SQL::OnReload(Configuration::Conf &conf)
|
||||
{
|
||||
const auto &block = Config->GetModule(this);
|
||||
prefix = block.Get<const Anope::string>("prefix", "anope_");
|
||||
GeoIPDB = block.Get<const Anope::string>("geoip_database");
|
||||
ctcpuser = block.Get<bool>("ctcpuser", "no");
|
||||
ctcpeob = block.Get<bool>("ctcpeob", "yes");
|
||||
Anope::string engine = block.Get<const Anope::string>("engine");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
|
||||
if (sql)
|
||||
this->CheckTables();
|
||||
else
|
||||
Log() << "IRC2SQL: no database connection to " << engine;
|
||||
|
||||
const Anope::string &snick = block.Get<const Anope::string>("client");
|
||||
if (snick.empty())
|
||||
throw ConfigException(Module::name + ": <client> must be defined");
|
||||
StatServ = BotInfo::Find(snick, true);
|
||||
if (!StatServ)
|
||||
throw ConfigException(Module::name + ": no bot named " + snick);
|
||||
|
||||
if (firstrun)
|
||||
{
|
||||
firstrun = false;
|
||||
|
||||
for (Anope::map<Server *>::const_iterator it = Servers::ByName.begin(); it != Servers::ByName.end(); ++it)
|
||||
{
|
||||
this->OnNewServer(it->second);
|
||||
}
|
||||
|
||||
for (const auto &[_, c] : ChannelList)
|
||||
{
|
||||
this->OnChannelCreate(c);
|
||||
}
|
||||
|
||||
for (const auto &[_, u] : UserListByNick)
|
||||
{
|
||||
bool exempt = false;
|
||||
this->OnUserConnect(u, exempt);
|
||||
for (const auto &[_, uc] : u->chans)
|
||||
{
|
||||
this->OnJoinChannel(u, uc->chan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void IRC2SQL::OnNewServer(Server *server)
|
||||
{
|
||||
query = "INSERT DELAYED INTO `" + prefix + "server` (name, hops, comment, link_time, online, ulined) "
|
||||
"VALUES (@name@, @hops@, @comment@, now(), 'Y', @ulined@) "
|
||||
"ON DUPLICATE KEY UPDATE name=VALUES(name), hops=VALUES(hops), comment=VALUES(comment), "
|
||||
"link_time=VALUES(link_time), online=VALUES(online), ulined=VALUES(ulined)";
|
||||
query.SetValue("name", server->GetName());
|
||||
query.SetValue("hops", server->GetHops());
|
||||
query.SetValue("comment", server->GetDescription());
|
||||
query.SetValue("ulined", server->IsULined() ? "Y" : "N");
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnServerQuit(Server *server)
|
||||
{
|
||||
if (quitting)
|
||||
return;
|
||||
|
||||
query = "CALL " + prefix + "ServerQuit(@name@)";
|
||||
query.SetValue("name", server->GetName());
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnUserConnect(User *u, bool &exempt)
|
||||
{
|
||||
if (!introduced_myself)
|
||||
{
|
||||
this->OnNewServer(Me);
|
||||
introduced_myself = true;
|
||||
}
|
||||
|
||||
query = "CALL " + prefix + "UserConnect(@nick@,@host@,@vhost@,@chost@,@realname@,@ip@,@ident@,@vident@,"
|
||||
"@account@,@secure@,@fingerprint@,@signon@,@server@,@uuid@,@modes@,@oper@)";
|
||||
query.SetValue("nick", u->nick);
|
||||
query.SetValue("host", u->host);
|
||||
query.SetValue("vhost", u->vhost);
|
||||
query.SetValue("chost", u->chost);
|
||||
query.SetValue("realname", u->realname);
|
||||
query.SetValue("ip", u->ip.addr());
|
||||
query.SetValue("ident", u->GetIdent());
|
||||
query.SetValue("vident", u->GetVIdent());
|
||||
query.SetValue("secure", u->IsSecurelyConnected() ? "Y" : "N");
|
||||
query.SetValue("account", u->IsIdentified() ? u->Account()->display : "");
|
||||
query.SetValue("fingerprint", u->fingerprint);
|
||||
query.SetValue("signon", u->signon);
|
||||
query.SetValue("server", u->server->GetName());
|
||||
query.SetValue("uuid", u->GetUID());
|
||||
query.SetValue("modes", u->GetModes());
|
||||
query.SetValue("oper", u->HasMode("OPER") ? "Y" : "N");
|
||||
this->RunQuery(query);
|
||||
|
||||
if (ctcpuser && (Me->IsSynced() || ctcpeob) && u->server != Me)
|
||||
IRCD->SendPrivmsg(StatServ, u->GetUID(), Anope::FormatCTCP("VERSION"));
|
||||
|
||||
}
|
||||
|
||||
void IRC2SQL::OnUserQuit(User *u, const Anope::string &msg)
|
||||
{
|
||||
if (quitting || u->server->IsQuitting())
|
||||
return;
|
||||
|
||||
query = "CALL " + prefix + "UserQuit(@nick@)";
|
||||
query.SetValue("nick", u->nick);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnUserNickChange(User *u, const Anope::string &oldnick)
|
||||
{
|
||||
query = "UPDATE `" + prefix + "user` SET nick=@newnick@ WHERE nick=@oldnick@";
|
||||
query.SetValue("newnick", u->nick);
|
||||
query.SetValue("oldnick", oldnick);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnUserAway(User *u, const Anope::string &message)
|
||||
{
|
||||
query = "UPDATE `" + prefix + "user` SET away=@away@, awaymsg=@awaymsg@ WHERE nick=@nick@";
|
||||
query.SetValue("away", (!message.empty()) ? "Y" : "N");
|
||||
query.SetValue("awaymsg", message);
|
||||
query.SetValue("nick", u->nick);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnFingerprint(User *u)
|
||||
{
|
||||
query = "UPDATE `" + prefix + "user` SET secure=@secure@, fingerprint=@fingerprint@ WHERE nick=@nick@";
|
||||
query.SetValue("secure", u->IsSecurelyConnected() ? "Y" : "N");
|
||||
query.SetValue("fingerprint", u->fingerprint);
|
||||
query.SetValue("nick", u->nick);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname)
|
||||
{
|
||||
query = "UPDATE `" + prefix + "user` SET modes=@modes@, oper=@oper@ WHERE nick=@nick@";
|
||||
query.SetValue("nick", u->nick);
|
||||
query.SetValue("modes", u->GetModes());
|
||||
query.SetValue("oper", u->HasMode("OPER") ? "Y" : "N");
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname)
|
||||
{
|
||||
this->OnUserModeSet(setter, u, mname);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnUserLogin(User *u)
|
||||
{
|
||||
query = "UPDATE `" + prefix + "user` SET account=@account@ WHERE nick=@nick@";
|
||||
query.SetValue("nick", u->nick);
|
||||
query.SetValue("account", u->IsIdentified() ? u->Account()->display : "");
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnNickLogout(User *u)
|
||||
{
|
||||
this->OnUserLogin(u);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnSetDisplayedHost(User *u)
|
||||
{
|
||||
query = "UPDATE `" + prefix + "user` "
|
||||
"SET vhost=@vhost@ "
|
||||
"WHERE nick=@nick@";
|
||||
query.SetValue("vhost", u->GetDisplayedHost());
|
||||
query.SetValue("nick", u->nick);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnChannelCreate(Channel *c)
|
||||
{
|
||||
query = "INSERT INTO `" + prefix + "chan` (channel, topic, topicauthor, topictime, modes) "
|
||||
"VALUES (@channel@,@topic@,@topicauthor@,@topictime@,@modes@) "
|
||||
"ON DUPLICATE KEY UPDATE channel=VALUES(channel), topic=VALUES(topic),"
|
||||
"topicauthor=VALUES(topicauthor), topictime=VALUES(topictime), modes=VALUES(modes)";
|
||||
query.SetValue("channel", c->name);
|
||||
query.SetValue("topic", c->topic);
|
||||
query.SetValue("topicauthor", c->topic_setter);
|
||||
if (c->topic_ts > 0)
|
||||
query.SetValue("topictime", c->topic_ts);
|
||||
else
|
||||
query.SetValue("topictime", "NULL", false);
|
||||
query.SetValue("modes", c->GetModes(true,true));
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnChannelDelete(Channel *c)
|
||||
{
|
||||
query = "DELETE FROM `" + prefix + "chan` WHERE channel=@channel@";
|
||||
query.SetValue("channel", c->name);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnJoinChannel(User *u, Channel *c)
|
||||
{
|
||||
Anope::string modes;
|
||||
ChanUserContainer *cu = u->FindChannel(c);
|
||||
if (cu)
|
||||
modes = cu->status.Modes();
|
||||
|
||||
query = "CALL " + prefix + "JoinUser(@nick@,@channel@,@modes@)";
|
||||
query.SetValue("nick", u->nick);
|
||||
query.SetValue("channel", c->name);
|
||||
query.SetValue("modes", modes);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
EventReturn IRC2SQL::OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data)
|
||||
{
|
||||
if (mode->type == MODE_STATUS)
|
||||
{
|
||||
User *u = User::Find(data.value);
|
||||
if (u == NULL)
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
ChanUserContainer *cc = u->FindChannel(c);
|
||||
if (cc == NULL)
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
query = "UPDATE `" + prefix + "user` AS u, `" + prefix + "ison` AS i, `" + prefix + "chan` AS c"
|
||||
" SET i.modes=@modes@"
|
||||
" WHERE u.nick=@nick@ AND c.channel=@channel@"
|
||||
" AND u.nickid = i.nickid AND c.chanid = i.chanid";
|
||||
query.SetValue("nick", u->nick);
|
||||
query.SetValue("modes", cc->status.Modes());
|
||||
query.SetValue("channel", c->name);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
else
|
||||
{
|
||||
query = "UPDATE `" + prefix + "chan` SET modes=@modes@ WHERE channel=@channel@";
|
||||
query.SetValue("channel", c->name);
|
||||
query.SetValue("modes", c->GetModes(true,true));
|
||||
this->RunQuery(query);
|
||||
}
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn IRC2SQL::OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m)
|
||||
{
|
||||
this->OnChannelModeSet(c, setter, mode, param);
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void IRC2SQL::OnLeaveChannel(User *u, Channel *c)
|
||||
{
|
||||
if (quitting)
|
||||
return;
|
||||
/*
|
||||
* user is quitting, we already received a OnUserQuit()
|
||||
* at this point the user is already removed from SQL and all channels
|
||||
*/
|
||||
if (u->Quitting())
|
||||
return;
|
||||
query = "CALL " + prefix + "PartUser(@nick@,@channel@)";
|
||||
query.SetValue("nick", u->nick);
|
||||
query.SetValue("channel", c->name);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic)
|
||||
{
|
||||
query = "UPDATE `" + prefix + "chan` "
|
||||
"SET topic=@topic@, topicauthor=@author@, topictime=FROM_UNIXTIME(@time@) "
|
||||
"WHERE channel=@channel@";
|
||||
query.SetValue("topic", c->topic);
|
||||
query.SetValue("author", c->topic_setter);
|
||||
query.SetValue("time", c->topic_ts);
|
||||
query.SetValue("channel", c->name);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnBotNotice(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
if (bi != StatServ)
|
||||
return;
|
||||
|
||||
Anope::string ctcpname, ctcpbody;
|
||||
if (!Anope::ParseCTCP(message, ctcpname, ctcpbody) || ctcpname != "VERSION")
|
||||
return;
|
||||
|
||||
if (u->HasExt("CTCPVERSION"))
|
||||
return;
|
||||
|
||||
u->Extend<bool>("CTCPVERSION");
|
||||
auto versionstr = Anope::NormalizeBuffer(ctcpbody);
|
||||
if (versionstr.empty())
|
||||
return;
|
||||
|
||||
query = "UPDATE `" + prefix + "user` "
|
||||
"SET version=@version@ "
|
||||
"WHERE nick=@nick@";
|
||||
query.SetValue("version", versionstr);
|
||||
query.SetValue("nick", u->nick);
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
MODULE_INIT(IRC2SQL)
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2013-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/sql.h"
|
||||
|
||||
class MySQLInterface final
|
||||
: public SQL::Interface
|
||||
{
|
||||
public:
|
||||
MySQLInterface(Module *o) : SQL::Interface(o) { }
|
||||
|
||||
void OnResult(const SQL::Result &r) override
|
||||
{
|
||||
}
|
||||
|
||||
void OnError(const SQL::Result &r) override
|
||||
{
|
||||
if (!r.GetQuery().query.empty())
|
||||
Log(LOG_DEBUG) << "irc2sql: Error executing query " << r.finished_query << ": " << r.GetError();
|
||||
else
|
||||
Log(LOG_DEBUG) << "irc2sql: Error executing query: " << r.GetError();
|
||||
}
|
||||
};
|
||||
|
||||
class IRC2SQL final
|
||||
: public Module
|
||||
{
|
||||
ServiceReference<SQL::Provider> sql;
|
||||
MySQLInterface sqlinterface;
|
||||
SQL::Query query;
|
||||
std::vector<Anope::string> TableList, ProcedureList, EventList;
|
||||
Anope::string prefix, GeoIPDB;
|
||||
bool quitting, introduced_myself, ctcpuser, ctcpeob, firstrun;
|
||||
BotInfo *StatServ;
|
||||
PrimitiveExtensibleItem<bool> versionreply;
|
||||
|
||||
void RunQuery(const SQL::Query &q);
|
||||
void GetTables();
|
||||
|
||||
bool HasTable(const Anope::string &table);
|
||||
bool HasProcedure(const Anope::string &table);
|
||||
bool HasEvent(const Anope::string &table);
|
||||
|
||||
void CheckTables();
|
||||
|
||||
public:
|
||||
IRC2SQL(const Anope::string &modname, const Anope::string &creator) :
|
||||
Module(modname, creator, EXTRA | VENDOR), sql("", ""), sqlinterface(this), versionreply(this, "CTCPVERSION")
|
||||
{
|
||||
firstrun = true;
|
||||
quitting = false;
|
||||
introduced_myself = false;
|
||||
}
|
||||
|
||||
void OnShutdown() override;
|
||||
void OnReload(Configuration::Conf &config) override;
|
||||
void OnNewServer(Server *server) override;
|
||||
void OnServerQuit(Server *server) override;
|
||||
void OnUserConnect(User *u, bool &exempt) override;
|
||||
void OnUserQuit(User *u, const Anope::string &msg) override;
|
||||
void OnUserNickChange(User *u, const Anope::string &oldnick) override;
|
||||
void OnUserAway(User *u, const Anope::string &message) override;
|
||||
void OnFingerprint(User *u) override;
|
||||
void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) override;
|
||||
void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) override;
|
||||
void OnUserLogin(User *u) override;
|
||||
void OnNickLogout(User *u) override;
|
||||
void OnSetDisplayedHost(User *u) override;
|
||||
|
||||
void OnChannelCreate(Channel *c) override;
|
||||
void OnChannelDelete(Channel *c) override;
|
||||
void OnLeaveChannel(User *u, Channel *c) override;
|
||||
void OnJoinChannel(User *u, Channel *c) override;
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const ModeData &data) override;
|
||||
EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override;
|
||||
|
||||
void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) override;
|
||||
|
||||
void OnBotNotice(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) override;
|
||||
};
|
||||
@@ -1,343 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2013-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#include "irc2sql.h"
|
||||
|
||||
void IRC2SQL::CheckTables()
|
||||
{
|
||||
Anope::string geoquery("");
|
||||
|
||||
if (firstrun)
|
||||
{
|
||||
/*
|
||||
* reset some tables to make sure they are really empty
|
||||
*/
|
||||
this->sql->RunQuery("TRUNCATE TABLE " + prefix + "user");
|
||||
this->sql->RunQuery("TRUNCATE TABLE " + prefix + "chan");
|
||||
this->sql->RunQuery("TRUNCATE TABLE " + prefix + "ison");
|
||||
this->sql->RunQuery("UPDATE `" + prefix + "server` SET currentusers=0, online='N'");
|
||||
}
|
||||
|
||||
this->GetTables();
|
||||
|
||||
if (GeoIPDB.equals_ci("country"))
|
||||
{
|
||||
if (!this->HasTable(prefix + "geoip_country"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "geoip_country` ("
|
||||
"`start` INT UNSIGNED NOT NULL,"
|
||||
"`end` INT UNSIGNED NOT NULL,"
|
||||
"`countrycode` varchar(2),"
|
||||
"`countryname` varchar(50),"
|
||||
"PRIMARY KEY `end` (`end`),"
|
||||
"KEY `start` (`start`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
}
|
||||
else if (GeoIPDB.equals_ci("city"))
|
||||
{
|
||||
if (!this->HasTable(prefix + "geoip_city_blocks"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "geoip_city_blocks` ("
|
||||
"`start` INT UNSIGNED NOT NULL,"
|
||||
"`end` INT UNSIGNED NOT NULL,"
|
||||
"`locId` INT UNSIGNED NOT NULL,"
|
||||
"PRIMARY KEY `end` (`end`),"
|
||||
"KEY `start` (`start`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
if (!this->HasTable(prefix + "geoip_city_location"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "geoip_city_location` ("
|
||||
"`locId` INT UNSIGNED NOT NULL,"
|
||||
"`country` CHAR(2) NOT NULL,"
|
||||
"`region` CHAR(2) NOT NULL,"
|
||||
"`city` VARCHAR(50),"
|
||||
"`latitude` FLOAT,"
|
||||
"`longitude` FLOAT,"
|
||||
"`areaCode` INT,"
|
||||
"PRIMARY KEY (`locId`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
if (!this->HasTable(prefix + "geoip_city_region"))
|
||||
{ query = "CREATE TABLE `" + prefix + "geoip_city_region` ("
|
||||
"`country` CHAR(2) NOT NULL,"
|
||||
"`region` CHAR(2) NOT NULL,"
|
||||
"`regionname` VARCHAR(100) NOT NULL,"
|
||||
"PRIMARY KEY (`country`,`region`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
}
|
||||
if (!this->HasTable(prefix + "server"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "server` ("
|
||||
"`id` int UNSIGNED NOT NULL AUTO_INCREMENT,"
|
||||
"`name` varchar(64) 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 DEFAULT 0,"
|
||||
"`online` enum('Y','N') NOT NULL DEFAULT 'Y',"
|
||||
"`ulined` enum('Y','N') NOT NULL DEFAULT 'N',"
|
||||
"PRIMARY KEY (`id`),"
|
||||
"UNIQUE KEY `name` (`name`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
if (!this->HasTable(prefix + "chan"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "chan` ("
|
||||
"`chanid` int UNSIGNED NOT NULL AUTO_INCREMENT,"
|
||||
"`channel` varchar(255) NOT NULL,"
|
||||
"`topic` varchar(512) DEFAULT NULL,"
|
||||
"`topicauthor` varchar(255) DEFAULT NULL,"
|
||||
"`topictime` datetime DEFAULT NULL,"
|
||||
"`modes` varchar(512) DEFAULT NULL,"
|
||||
"PRIMARY KEY (`chanid`),"
|
||||
"UNIQUE KEY `channel`(`channel`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
if (!this->HasTable(prefix + "user"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "user` ("
|
||||
"`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 '',"
|
||||
"`chost` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`realname` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`ip` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`ident` varchar(32) NOT NULL DEFAULT '',"
|
||||
"`vident` varchar(32) NOT NULL DEFAULT '',"
|
||||
"`modes` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`account` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`secure` enum('Y','N') NOT NULL DEFAULT 'N',"
|
||||
"`fingerprint` varchar(128) NOT NULL DEFAULT '',"
|
||||
"`signon` datetime DEFAULT NULL,"
|
||||
"`server` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`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',"
|
||||
"`awaymsg` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`version` varchar(255) NOT NULL DEFAULT '',"
|
||||
"`geocode` varchar(16) NOT NULL DEFAULT '',"
|
||||
"`geocountry` varchar(64) NOT NULL DEFAULT '',"
|
||||
"`georegion` varchar(100) NOT NULL DEFAULT '',"
|
||||
"`geocity` varchar(128) NOT NULL DEFAULT '',"
|
||||
"`locId` INT UNSIGNED,"
|
||||
"PRIMARY KEY (`nickid`),"
|
||||
"UNIQUE KEY `nick` (`nick`),"
|
||||
"KEY `servid` (`servid`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
if (!this->HasTable(prefix + "ison"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "ison` ("
|
||||
"`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`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
if (!this->HasTable(prefix + "maxusers"))
|
||||
{
|
||||
query = "CREATE TABLE `" + prefix + "maxusers` ("
|
||||
"`name` VARCHAR(255) NOT NULL,"
|
||||
"`maxusers` int NOT NULL,"
|
||||
"`maxtime` DATETIME NOT NULL,"
|
||||
"`lastused` DATETIME NOT NULL,"
|
||||
"UNIQUE KEY `name` (`name`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
if (this->HasProcedure(prefix + "UserConnect"))
|
||||
this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "UserConnect"));
|
||||
|
||||
if (GeoIPDB.equals_ci("country"))
|
||||
geoquery = "UPDATE `" + prefix + "user` AS u "
|
||||
"JOIN ( SELECT `countrycode`, `countryname` "
|
||||
"FROM `" + prefix + "geoip_country` "
|
||||
"WHERE INET_ATON(ip_) <= `end` "
|
||||
"AND `start` <= INET_ATON(ip_) "
|
||||
"ORDER BY `end` ASC LIMIT 1 ) as c "
|
||||
"SET u.geocode = c.countrycode, u.geocountry = c.countryname "
|
||||
"WHERE u.nick = nick_; ";
|
||||
else if (GeoIPDB.equals_ci("city"))
|
||||
geoquery = "UPDATE `" + prefix + "user` as u "
|
||||
"JOIN ( SELECT * FROM `" + prefix + "geoip_city_location` "
|
||||
"WHERE `locID` = ( SELECT `locID` "
|
||||
"FROM `" + prefix + "geoip_city_blocks` "
|
||||
"WHERE INET_ATON(ip_) <= `end` "
|
||||
"AND `start` <= INET_ATON(ip_) "
|
||||
"ORDER BY `end` ASC LIMIT 1 ) "
|
||||
") as l "
|
||||
"SET u.geocode = l.country, "
|
||||
"u.geocity = l.city, "
|
||||
"u.locID = l.locID, "
|
||||
"u.georegion = ( SELECT `regionname` "
|
||||
"FROM `" + prefix + "geoip_city_region` "
|
||||
"WHERE `country` = l.country "
|
||||
"AND `region` = l.region )"
|
||||
"WHERE u.nick = nick_;";
|
||||
|
||||
query = "CREATE PROCEDURE `" + prefix + "UserConnect`"
|
||||
"(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, "
|
||||
"server_ varchar(255), uuid_ varchar(32), modes_ varchar(255), "
|
||||
"oper_ enum('Y','N')) "
|
||||
"BEGIN "
|
||||
"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) "
|
||||
"VALUES (nick_, host_, vhost_, chost_, realname_, ip_, ident_, vident_, "
|
||||
"account_, secure_, fingerprint_, FROM_UNIXTIME(signon_), server_, "
|
||||
"uuid_, modes_, oper_) "
|
||||
"ON DUPLICATE KEY UPDATE host=VALUES(host), vhost=VALUES(vhost), "
|
||||
"chost=VALUES(chost), realname=VALUES(realname), ip=VALUES(ip), "
|
||||
"ident=VALUES(ident), vident=VALUES(vident), account=VALUES(account), "
|
||||
"secure=VALUES(secure), fingerprint=VALUES(fingerprint), signon=VALUES(signon), "
|
||||
"server=VALUES(server), uuid=VALUES(uuid), modes=VALUES(modes), "
|
||||
"oper=VALUES(oper);"
|
||||
"UPDATE `" + prefix + "user` as `u`, `" + prefix + "server` as `s`"
|
||||
"SET u.servid = s.id, "
|
||||
"s.currentusers = s.currentusers + 1 "
|
||||
"WHERE s.name = server_ AND u.nick = nick_;"
|
||||
"SELECT `currentusers` INTO cur FROM `" + prefix + "server` WHERE name=server_;"
|
||||
"SELECT `maxusers` INTO max FROM `" + prefix + "maxusers` WHERE name=server_;"
|
||||
"IF found_rows() AND cur <= max THEN "
|
||||
"UPDATE `" + prefix + "maxusers` SET lastused=now() WHERE name=server_;"
|
||||
"ELSE "
|
||||
"INSERT INTO `" + prefix + "maxusers` (name, maxusers, maxtime, lastused) "
|
||||
"VALUES ( server_, cur, now(), now() ) "
|
||||
"ON DUPLICATE KEY UPDATE "
|
||||
"name=VALUES(name), maxusers=VALUES(maxusers),"
|
||||
"maxtime=VALUES(maxtime), lastused=VALUES(lastused);"
|
||||
"END IF;"
|
||||
+ geoquery +
|
||||
"END";
|
||||
this->RunQuery(query);
|
||||
|
||||
if (this->HasProcedure(prefix + "ServerQuit"))
|
||||
this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "ServerQuit"));
|
||||
query = "CREATE PROCEDURE " + prefix + "ServerQuit(sname_ varchar(255)) "
|
||||
"BEGIN "
|
||||
/* 1.
|
||||
* remove all users on the splitting server from the ison table
|
||||
*/
|
||||
"DELETE i FROM `" + prefix + "ison` AS i "
|
||||
"INNER JOIN `" + prefix + "server` AS s "
|
||||
"INNER JOIN `" + prefix + "user` AS u "
|
||||
"WHERE i.nickid = u.nickid "
|
||||
"AND u.servid = s.id "
|
||||
"AND s.name = sname_;"
|
||||
|
||||
/* 2.
|
||||
* remove all users on the splitting server from the user table
|
||||
*/
|
||||
"DELETE u FROM `" + prefix + "user` AS u "
|
||||
"INNER JOIN `" + prefix + "server` AS s "
|
||||
"WHERE s.id = u.servid "
|
||||
"AND s.name = sname_;"
|
||||
|
||||
/* 3.
|
||||
* on the splitting server, set usercount = 0, split_time = now(), online = 'N'
|
||||
*/
|
||||
"UPDATE `" + prefix + "server` SET currentusers = 0, split_time = now(), online = 'N' "
|
||||
"WHERE name = sname_;"
|
||||
"END;"; // end of the procedure
|
||||
this->RunQuery(query);
|
||||
|
||||
|
||||
if (this->HasProcedure(prefix + "UserQuit"))
|
||||
this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "UserQuit"));
|
||||
query = "CREATE PROCEDURE `" + prefix + "UserQuit`"
|
||||
"(nick_ varchar(255)) "
|
||||
"BEGIN "
|
||||
/* decrease usercount on the server where the user was on */
|
||||
"UPDATE `" + prefix + "user` AS `u`, `" + prefix + "server` AS `s` "
|
||||
"SET s.currentusers = s.currentusers - 1 "
|
||||
"WHERE u.nick=nick_ AND u.servid = s.id; "
|
||||
/* remove from all channels where the user was on */
|
||||
"DELETE i FROM `" + prefix + "ison` AS i "
|
||||
"INNER JOIN `" + prefix + "user` as u "
|
||||
"WHERE u.nick = nick_ "
|
||||
"AND i.nickid = u.nickid;"
|
||||
/* remove the user from the user table */
|
||||
"DELETE FROM `" + prefix + "user` WHERE nick = nick_; "
|
||||
"END";
|
||||
this->RunQuery(query);
|
||||
|
||||
if (this->HasProcedure(prefix + "ShutDown"))
|
||||
this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "ShutDown"));
|
||||
query = "CREATE PROCEDURE `" + prefix + "ShutDown`()"
|
||||
"BEGIN "
|
||||
"UPDATE `" + prefix + "server` "
|
||||
"SET currentusers=0, online='N', split_time=now();"
|
||||
"TRUNCATE TABLE `" + prefix + "user`;"
|
||||
"TRUNCATE TABLE `" + prefix + "chan`;"
|
||||
"TRUNCATE TABLE `" + prefix + "ison`;"
|
||||
"END";
|
||||
this->RunQuery(query);
|
||||
|
||||
if (this->HasProcedure(prefix + "JoinUser"))
|
||||
this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "JoinUser"));
|
||||
query = "CREATE PROCEDURE `"+ prefix + "JoinUser`"
|
||||
"(nick_ varchar(255), channel_ varchar(255), modes_ varchar(255)) "
|
||||
"BEGIN "
|
||||
"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 "
|
||||
"WHERE u.nick=nick_ AND c.channel=channel_;"
|
||||
"SELECT count(i.chanid) INTO cur "
|
||||
"FROM `" + prefix + "chan` AS c, " + prefix + "ison AS i "
|
||||
"WHERE i.chanid = c.chanid AND c.channel=channel_;"
|
||||
"SELECT `maxusers` INTO max FROM `" + prefix + "maxusers` WHERE name=channel_;"
|
||||
"IF found_rows() AND cur <= max THEN "
|
||||
"UPDATE `" + prefix + "maxusers` SET lastused=now() WHERE name=channel_;"
|
||||
"ELSE "
|
||||
"INSERT INTO `" + prefix + "maxusers` (name, maxusers, maxtime, lastused) "
|
||||
"VALUES ( channel_, cur, now(), now() ) "
|
||||
"ON DUPLICATE KEY UPDATE "
|
||||
"name=VALUES(name), maxusers=VALUES(maxusers),"
|
||||
"maxtime=VALUES(maxtime), lastused=VALUES(lastused);"
|
||||
"END IF;"
|
||||
"END";
|
||||
this->RunQuery(query);
|
||||
|
||||
if (this->HasProcedure(prefix + "PartUser"))
|
||||
this->RunQuery(SQL::Query("DROP PROCEDURE " + prefix + "PartUser"));
|
||||
query = "CREATE PROCEDURE `" + prefix + "PartUser`"
|
||||
"(nick_ varchar(255), channel_ varchar(255)) "
|
||||
"BEGIN "
|
||||
"DELETE i FROM `" + prefix + "ison` AS i "
|
||||
"INNER JOIN `" + prefix + "user` AS u "
|
||||
"INNER JOIN `" + prefix + "chan` AS c "
|
||||
"WHERE i.nickid = u.nickid "
|
||||
"AND u.nick = nick_ "
|
||||
"AND i.chanid = c.chanid "
|
||||
"AND c.channel = channel_;"
|
||||
"END";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2013-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#include "irc2sql.h"
|
||||
|
||||
void IRC2SQL::RunQuery(const SQL::Query &q)
|
||||
{
|
||||
if (sql)
|
||||
sql->Run(&sqlinterface, q);
|
||||
}
|
||||
|
||||
void IRC2SQL::GetTables()
|
||||
{
|
||||
TableList.clear();
|
||||
ProcedureList.clear();
|
||||
EventList.clear();
|
||||
if (!sql)
|
||||
return;
|
||||
|
||||
SQL::Result r = this->sql->RunQuery(this->sql->GetTables(prefix));
|
||||
for (int i = 0; i < r.Rows(); ++i)
|
||||
{
|
||||
const std::map<Anope::string, Anope::string> &map = r.Row(i);
|
||||
for (std::map<Anope::string, Anope::string>::const_iterator it = map.begin(); it != map.end(); ++it)
|
||||
TableList.push_back(it->second);
|
||||
}
|
||||
query = "SHOW PROCEDURE STATUS WHERE `Db` = Database();";
|
||||
r = this->sql->RunQuery(query);
|
||||
for (int i = 0; i < r.Rows(); ++i)
|
||||
{
|
||||
ProcedureList.push_back(r.Get(i, "Name"));
|
||||
}
|
||||
query = "SHOW EVENTS WHERE `Db` = Database();";
|
||||
r = this->sql->RunQuery(query);
|
||||
for (int i = 0; i < r.Rows(); ++i)
|
||||
{
|
||||
EventList.push_back(r.Get(i, "Name"));
|
||||
}
|
||||
}
|
||||
|
||||
bool IRC2SQL::HasTable(const Anope::string &table)
|
||||
{
|
||||
for (std::vector<Anope::string>::const_iterator it = TableList.begin(); it != TableList.end(); ++it)
|
||||
if (*it == table)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRC2SQL::HasProcedure(const Anope::string &table)
|
||||
{
|
||||
for (std::vector<Anope::string>::const_iterator it = ProcedureList.begin(); it != ProcedureList.end(); ++it)
|
||||
if (*it == table)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRC2SQL::HasEvent(const Anope::string &table)
|
||||
{
|
||||
for (std::vector<Anope::string>::const_iterator it = EventList.begin(); it != EventList.end(); ++it)
|
||||
if (*it == table)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -41,9 +41,6 @@ if(NOT WIN32)
|
||||
install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/anoperc
|
||||
DESTINATION ${BIN_DIR}
|
||||
)
|
||||
install (PROGRAMS geoipupdate.sh
|
||||
DESTINATION ${BIN_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# On non-Windows platforms, if RUNGROUP is set, change the permissions of the tools directory
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script is a helper script for the irc2sql module.
|
||||
# It downloads the configured geoip databases and inserts
|
||||
# them into existing mysql tables. The tables are created
|
||||
# by the irc2sql module on the first load.
|
||||
|
||||
# Don't forget to rename this file or your changes
|
||||
# will be overwritten on the next 'make install'
|
||||
|
||||
############################
|
||||
# Config
|
||||
############################
|
||||
|
||||
|
||||
geoip_database="country" # available options: "country" and "city"
|
||||
mysql_host="localhost"
|
||||
mysql_user="anope"
|
||||
mysql_password="anope"
|
||||
mysql_database="anope"
|
||||
prefix="anope_"
|
||||
die="yes"
|
||||
|
||||
###########################
|
||||
|
||||
# The GeoIP data is created by MaxMind, available from www.maxmind.com.
|
||||
geoip_country_source="https://mirrors-cdn.liferay.com/geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip"
|
||||
geoip_city_source="https://mirrors-cdn.liferay.com/geolite.maxmind.com/download/geoip/database/GeoLiteCity-latest.tar.xz"
|
||||
geoip_region_source="https://www.maxmind.com/download/geoip/misc/region_codes.csv"
|
||||
|
||||
###########################
|
||||
LOGIN="--host=$mysql_host --user=$mysql_user --password=$mysql_password $mysql_database"
|
||||
PARAMS="--delete --local --fields-terminated-by=, --fields-enclosed-by=\" --lines-terminated-by=\n $LOGIN"
|
||||
|
||||
download() {
|
||||
local url=$1
|
||||
local desc=$2
|
||||
echo -n " $desc "
|
||||
wget --progress=dot $url 2>&1 | grep --line-buffered "%" | sed -u -e "s,\.,,g" | awk '{printf("\b\b\b\b%4s", $2)}'
|
||||
echo -ne " Done\n"
|
||||
}
|
||||
|
||||
|
||||
if test $die = "yes"; then
|
||||
echo "You have to edit and configure this script first."
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
if test $geoip_database = "country"; then
|
||||
echo "Downloading..."
|
||||
download "$geoip_country_source" "Country Database:"
|
||||
echo "Unpacking..."
|
||||
unzip -jo GeoIPCountryCSV.zip
|
||||
rm GeoIPCountryCSV.zip
|
||||
echo "Converting to UTF-8..."
|
||||
iconv -f ISO-8859-1 -t UTF-8 GeoIPCountryWhois.csv -o $prefix"geoip_country.csv"
|
||||
rm GeoIPCountryWhois.csv
|
||||
echo "Importing..."
|
||||
mysqlimport --columns=@x,@x,start,end,countrycode,countryname $PARAMS $prefix"geoip_country.csv"
|
||||
rm $prefix"geoip_country.csv" $prefix"geoip_country6.csv"
|
||||
echo "Done..."
|
||||
elif test $geoip_database = "city"; then
|
||||
echo "Downloading..."
|
||||
download "$geoip_city_source" "City Database:"
|
||||
download "$geoip_region_source" "Region Database:"
|
||||
echo "Unpacking..."
|
||||
tar -xf GeoLiteCity-latest.tar.xz --strip-components 1
|
||||
rm GeoLiteCity-latest.tar.xz
|
||||
echo "Converting to utf-8..."
|
||||
iconv -f ISO-8859-1 -t UTF-8 GeoLiteCity-Blocks.csv -o $prefix"geoip_city_blocks.csv"
|
||||
iconv -f ISO-8859-1 -t UTF-8 GeoLiteCity-Location.csv -o $prefix"geoip_city_location.csv"
|
||||
iconv -f ISO-8859-1 -t UTF-8 region_codes.csv -o $prefix"geoip_city_region.csv"
|
||||
rm GeoLiteCity-Blocks.csv GeoLiteCity-Location.csv region_codes.csv
|
||||
echo "Importing..."
|
||||
mysqlimport --columns=start,end,locID --ignore-lines=2 $PARAMS $prefix"geoip_city_blocks.csv"
|
||||
mysqlimport --columns=locID,country,region,city,@x,latitude,longitude,@x,areaCode --ignore-lines=2 $PARAMS $prefix"geoip_city_location.csv"
|
||||
mysqlimport --columns=country,region,regionname $PARAMS $prefix"geoip_city_region.csv"
|
||||
rm $prefix"geoip_city_blocks.csv" $prefix"geoip_city_location.csv" $prefix"geoip_city_region.csv"
|
||||
echo "Done..."
|
||||
fi
|
||||
Reference in New Issue
Block a user