From: Shane Synan Date: Wed, 30 May 2018 00:27:37 +0000 (-0500) Subject: common: Add '$i:identd', '*' for empty, tooltips X-Git-Tag: travis-deploy-test~79 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=71f48abcf1e4f9f852a2087bb30a2f187172c910 common: Add '$i:identd', '*' for empty, tooltips Add "$i:identd" paramater variable to aliases, representing the ident if verified, or "*" if unknown or unverified (prefixed with '~'). This allows for a general banning rule to target all idents for a nickname that doesn't provide verified idents (e.g. general clients), while limiting bans to specific idents for a nickname that provides a verified ident (e.g. shared bouncer/core). For example... /mode channel +b *!$1:identd:$1:hostname ...would target "*!*@bad.example.com" for someone connecting without an identd server, and "*!userid@shared.example.com" for someone connecting with an identd server. For all nickname-based parameters, substitute in "*" when empty instead of leaving it blank. This means using the variables for nicknames that haven't been WHO'd will still provide results. This may be dangerous if using the above example /ban alias on a nickname that doesn't have hostname information available, e.g. if you joined a channel after they did. Update alias tooltips with 'identd', and totally revamp them using the table layout for better readability and (hopefully?) easier translation. Update the comments in AliasManager, too, so it's a bit more readable. Thanks Exterminador for the suggestion/reporting, and @justJanne for further clarifications! --- diff --git a/src/common/aliasmanager.cpp b/src/common/aliasmanager.cpp index 9fcc567f..359db287 100644 --- a/src/common/aliasmanager.cpp +++ b/src/common/aliasmanager.cpp @@ -187,10 +187,43 @@ void AliasManager::expand(const QString &alias, const BufferInfo &bufferInfo, co } for (int j = params.count(); j > 0; j--) { + // Find the referenced IRC user... IrcUser *ircUser = net->ircUser(params[j - 1]); - command = command.replace(QString("$%1:hostname").arg(j), ircUser ? ircUser->host() : QString("*")); - command = command.replace(QString("$%1:ident").arg(j), ircUser ? ircUser->user() : QString("*")); - command = command.replace(QString("$%1:account").arg(j), ircUser ? ircUser->account() : QString("*")); + // ...and replace components, using short-circuit evaluation as ircUser might be null + + // Account, or "*" if blank/nonexistent/logged out + command = command.replace( + QString("$%1:account").arg(j), + (ircUser && !ircUser->account().isEmpty()) ? ircUser->account() + : QString("*")); + + // Hostname, or "*" if blank/nonexistent + command = command.replace( + QString("$%1:hostname").arg(j), + (ircUser && !ircUser->host().isEmpty()) ? ircUser->host() : QString("*")); + + // Identd + // Ident if verified, or "*" if blank/unknown/unverified (prefixed with "~") + // + // Most IRC daemons have the option to prefix an ident with "~" if it could not be + // verified via an identity daemon such as oidentd. In these cases, it can be handy to + // have a way to ban via ident if verified, or all idents if not verified. If the + // server does not verify idents, it usually won't add "~". + // + // Identd must be replaced before ident to avoid being treated as "$i:ident" + "d" + command = command.replace( + QString("$%1:identd").arg(j), + (ircUser && !ircUser->user().isEmpty() + && !ircUser->user().startsWith("~")) + ? ircUser->user() : QString("*")); + + // Ident, or "*" if blank/nonexistent + command = command.replace( + QString("$%1:ident").arg(j), + (ircUser && !ircUser->user().isEmpty()) ? ircUser->user() : QString("*")); + + // Nickname + // Must be replaced last to avoid interferring with more specific aliases command = command.replace(QString("$%1").arg(j), params[j - 1]); } command = command.replace("$0", msg); diff --git a/src/qtui/settingspages/aliasesmodel.cpp b/src/qtui/settingspages/aliasesmodel.cpp index fa885b93..569f56c6 100644 --- a/src/qtui/settingspages/aliasesmodel.cpp +++ b/src/qtui/settingspages/aliasesmodel.cpp @@ -58,19 +58,78 @@ QVariant AliasesModel::data(const QModelIndex &index, int role) const "It can be used as a regular slash command.

" "Example: \"foo\" can be used per /foo"); case 1: - return tr("The string the shortcut will be expanded to
" - "special variables:
" - " - $i represents the i'th parameter.
" - " - $i..j represents the i'th to j'th parameter separated by spaces.
" - " - $i.. represents all parameters from i on separated by spaces.
" - " - $i:hostname represents the hostname of the user identified by the i'th parameter or a * if unknown.
" - " - $i:ident represents the ident of the user identified by the i'th parameter or a * if unknown.
" - " - $i:account represents the account of the user identified by the i'th parameter or a * if logged out or unknown.
" - " - $0 the whole string.
" - " - $nick your current nickname
" - " - $channel the name of the selected channel

" - "Multiple commands can be separated with semicolons

" - "Example: \"Test $1; Test $2; Test All $0\" will be expanded to three separate messages \"Test 1\", \"Test 2\" and \"Test All 1 2 3\" when called like /test 1 2 3"); + { + // To avoid overwhelming the user, organize things into a table + QString strTooltip; + QTextStream tooltip( &strTooltip, QIODevice::WriteOnly ); + tooltip << ""; + + // Function to add a row to the tooltip table + auto addRow = [&]( + const QString& key, const QString& value = QString(), bool condition = true) { + if (condition) { + if (value.isEmpty()) { + tooltip << "" + << key << ""; + } else { + tooltip << "" + << key << "" << value << ""; + } + } + }; + + tooltip << "

" + << tr("The string the shortcut will be expanded to") << "

"; + + tooltip << "

" + << tr("Special variables") << "

"; + + // Variable option table + tooltip << ""; + + // Parameter variables + addRow(tr("Parameter variables")); + addRow("$i", tr("i'th parameter")); + addRow("$i..j", tr("i'th to j'th parameter separated by spaces")); + addRow("$i..", tr("all parameters from i on separated by spaces")); + + // IrcUser handling + addRow(tr("Nickname parameter variables")); + addRow("$i:account", + tr("account of user identified by i'th parameter, or a '*' if logged out or " + "unknown")); + addRow("$i:hostname", + tr("hostname of user identified by i'th parameter, or a '*' if unknown")); + addRow("$i:ident", + tr("ident of user identified by i'th parameter, or a '*' if unknown")); + addRow("$i:identd", + tr("ident of user identified by i'th parameter if verified, or a '*' if unknown " + "or unverified (prefixed with '~')")); + + // General variables + addRow(tr("General variables")); + addRow("$0", tr("the whole string")); + addRow("$nick", tr("your current nickname")); + addRow("$channel", tr("the name of the selected channel")); + + // End table + tooltip << "
"; + + // Example header + tooltip << "

" + << tr("Multiple commands can be separated with semicolons") << "

"; + // Example + tooltip << "

"; + tooltip << QString("

%1 %2
").arg( + tr("Example:"), tr("\"Test $1; Test $2; Test All $0\"")); + tooltip << tr("...will be expanded to three separate messages \"Test 1\", \"Test 2\" " + "and \"Test All 1 2 3\" when called like /test 1 2 3") + << "

"; + + // End tooltip + tooltip << "
"; + return strTooltip; + } default: return QVariant(); }