diff --git a/README.md b/README.md index 585d86c..d86632f 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,14 @@ MediaWiki extension for sending notifications to a Discord webhook from MediaWik - **MediaWiki 1.31+** ## Configuration -- `$wgDiscordWebhookURL` - String or array containing webhook URLs \ No newline at end of file +- `$wgDiscordWebhookURL` - A string or array containing webhook URLs + +### Optional + +- `$wgDiscordNoBots` - Do not send notifications that are triggered by a bot account - default: `true` +- `$wgDiscordNoMinor` - Do not send notifications that are for minor edits - default: `false` +- `$wgDiscordNoNull` - Do not send notifications for null edits - default: `true` + +## Hooks used +- `PageContentSaveComplete` - New edits to pages and page creations +- `ArticleDeleteComplete` - Page deletions \ No newline at end of file diff --git a/extension.json b/extension.json index f882b39..0a15e2f 100644 --- a/extension.json +++ b/extension.json @@ -9,10 +9,9 @@ "manifest_version": 1, "config": { "DiscordWebhookURL": [], - "DiscordNotificationsLanguage": "", - "DiscordExcludedNotifications": [], - "DiscordShowBotEdits": false, - "DiscordShowNullEdits": false + "DiscordNoBots": true, + "DiscordNoMinor": false, + "DiscordNoNull": true }, "AutoloadClasses": { "DiscordHooks": "src/DiscordHooks.php", @@ -22,6 +21,7 @@ "mw-discord": "i18n" }, "Hooks": { - "PageContentSaveComplete": "DiscordHooks::onPageContentSaveComplete" + "PageContentSaveComplete": "DiscordHooks::onPageContentSaveComplete", + "ArticleDeleteComplete": "DiscordHooks::onArticleDeleteComplete" } } diff --git a/src/DiscordHooks.php b/src/DiscordHooks.php index f33c933..b0e1fab 100644 --- a/src/DiscordHooks.php +++ b/src/DiscordHooks.php @@ -6,8 +6,49 @@ * @ingroup Extensions */ class DiscordHooks { - public static function onPageContentSaveComplete( &$wikiPage, &$user, $content, $summary, $isMinor, $revision ) { - DiscordUtils::handleDiscord('memes'); + /** + * Called when a page is created or edited + */ + public static function onPageContentSaveComplete( &$wikiPage, &$user, $content, $summary, $isMinor, $isWatch, $section, &$flags, $revision, &$status, $baseRevId, $undidRevId ) { + global $wgDiscordNoBots, $wgDiscordNoMinor, $wgDiscordNoNull; + + if ( $wgDiscordNoBots && $user->isBot() ) { + // Don't continue, this is a bot edit + return true; + } + + if ( $wgDiscordNoMinor && $isMinor ) { + // Don't continue, this is a minor edit + return true; + } + + if ( $wgDiscordNoNull && ( !$revision || is_null( $status->getValue()['revision'] ) ) ) { + // Don't continue, this is a null edit + return true; + } + + $msg .= DiscordUtils::createUserLinks( $user ) . ' edited '; + $msg .= DiscordUtils::createMarkdownLink( $wikiPage->getTitle(), $wikiPage->getTitle()->getFullUrl() ); + $msg .= ($summary ? (' `' . $summary . '` ' ) : ' ' ) . DiscordUtils::createRevisionText( $revision ); + DiscordUtils::handleDiscord($msg); + return true; + } + + /** + * Called when a page is deleted + */ + public static function onArticleDeleteComplete( &$article, User &$user, $reason, $id, $content, LogEntry $logEntry, $archivedRevisionCount ) { + global $wgDiscordNoBots, $wgDiscordNoMinor, $wgDiscordNoNull; + + if ( $wgDiscordNoBots && $user->isBot() ) { + // Don't continue, this is a bot change + return true; + } + + $msg .= DiscordUtils::createUserLinks( $user ) . ' deleted '; + $msg .= DiscordUtils::createMarkdownLink( $article->getTitle(), $article->getTitle()->getFullUrl() ); + $msg .= ($reason ? (' `' . $reason . '` ' ) : ' ' ) . "($archivedRevisionCount revisions deleted)"; + DiscordUtils::handleDiscord($msg); return true; } } diff --git a/src/Utils.php b/src/Utils.php index db2f7fb..140c503 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -57,17 +57,45 @@ class DiscordUtils { return $result; } - public static function CreateMarkdownLink ($text, $url) - { - return "[" . $text . "]" . "(" . self::EncodeUrl($url) . ")"; - } + /** + * Creates a formatted markdown link based on text and given URL + */ + public static function createMarkdownLink ($text, $url) { + return "[" . $text . "]" . "(" . self::encodeURL($url) . ")"; + } + + /** + * Creates links for a specific MediaWiki User object + */ + public static function createUserLinks ($user) { + $userPage = DiscordUtils::createMarkdownLink( $user, $user->getUserPage()->getFullUrl() ); + $userTalk = DiscordUtils::createMarkdownLink( 't', $user->getTalkPage()->getFullUrl() ); + $userContribs = DiscordUtils::createMarkdownLink( 'c', Title::newFromText("Special:Contributions/" . $user)->getFullURL() ); + return sprintf( "%s (%s|%s)", $userPage, $userTalk, $userContribs ); + } + + /** + * Creates formatted text for a specific Revision object + */ + public static function createRevisionText ($revision) { + $previous = $revision->getPrevious(); + $text = '(' . DiscordUtils::createMarkdownLink( 'diff', $revision->getTitle()->getFullUrl("diff=prev", ["oldid" => $revision->getID()]) ) . ') '; + if ($revision->isMinor()) { + $text .= '(m) '; + } + if ($previous) { + $text .= sprintf( "(%+d)", $revision->getSize() - $previous->getSize() ); + } + return $text; + } - public static function EncodeUrl($url) - { + /** + * Strip bad characters from a URL + */ + public static function encodeURL($url) { $url = str_replace(" ", "%20", $url); $url = str_replace("(", "%28", $url); $url = str_replace(")", "%29", $url); - return $url; }