Legoktm has uploaded a new change for review. https://gerrit.wikimedia.org/r/74831
Change subject: Initial commit of already written code ...................................................................... Initial commit of already written code Provides a special page to let users send a message to multiple users at once. I've already started adding in some global variables, but no actual functionality for that yet. Change-Id: I8566b7c13aca7ffa03cf443debd9a52923d04c69 --- A MassMessage.body.php A MassMessage.i18n.php A MassMessage.php A MassMessageJob.php A SpecialMassMessage.php 5 files changed, 445 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MassMessage refs/changes/31/74831/1 diff --git a/MassMessage.body.php b/MassMessage.body.php new file mode 100644 index 0000000..96b75f2 --- /dev/null +++ b/MassMessage.body.php @@ -0,0 +1,51 @@ +<?php + +/* + * Some core functions needed by the ex. + * Based on code from AbuseFilter + * https://mediawiki.org/wiki/Extension:AbuseFilter + * + * @file + * @author Kunal Mehta + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + */ + + + +class MassMessage { + + /* + * Sets up the messenger account for our use if it hasn't been already. + * + * @return User + * @fixme This should use the langage for the target site, not submission site + */ + public static function getMessengerUser() { + // Function kinda copied from the AbuseFilter + $user = User::newFromName( wfMessage( 'massmessage-sender' )->inContentLanguage()->text() ); + $user->load(); + if ( $user->getId() && $user->mPassword == '' ) { + // We've already stolen the account + return $user; + } + + if ( !$user->getId() ) { + $user->addToDatabase(); + $user->saveSettings(); + + // Increment site_stats.ss_users + $ssu = new SiteStatsUpdate( 0, 0, 0, 0, 1 ); + $ssu->doUpdate(); + } else { + // Someone already created the account, lets take it over. + $user->setPassword( null ); + $user->setEmail( null ); + $user->saveSettings(); + } + + // Make the user a bot so it doesn't look weird + $user->addGroup( 'sysop' ); + + return $user; + } +} \ No newline at end of file diff --git a/MassMessage.i18n.php b/MassMessage.i18n.php new file mode 100644 index 0000000..ebc7882 --- /dev/null +++ b/MassMessage.i18n.php @@ -0,0 +1,59 @@ +<?php + +/** +* Translations and stuff. +* +* @file +* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later +*/ + +$messages = array(); + + +/** English + * @author Kunal Mehta + */ + +$messages['en'] = array( + 'massmessage' => 'Send mass message', + 'massmessage-desc' => 'Allows users to easily send a message to a list of users', + 'massmessage-sender' => 'MessengerBot', + 'massmessage-form-spamlist' => 'Page containing list of pages to leave a message on.', + 'massmessage-form-subject' => 'Subject of the message. Will also be used as the edit summary.', + 'massmessage-form-message' => 'The body of the message.', + 'massmessage-form-global' => 'This is a global message.', + 'massmessage-form-submit' => 'Send', + 'massmessage-submitted' => 'Your message has been sent!', + 'massmessage-account-blocked' => 'The account used to deliver messages has been blocked.', + 'massmessage-spamlist-doesnotexist' => 'The input list of pages does not exist.', + 'right-massmessage' => 'Send a message to multiple users at once', + 'action-massmessage' => 'send a message to multiple users at once', + 'right-massmessage-global' => 'Send a message to multiple users on different wikis at once', + 'log-name-massmessage' => 'Mass message log', + 'log-description-massmessage' => 'These events track users sending messages through [[Special:MassMessage]].', + 'logentry-massmessage-send' => '$1 {{GENDER:$2|sent a message}} to $3' +); + +/** Message documentation + * @author Kunal Mehta + */ +$messages['qqq'] = array( + 'massmessage' => '{{doc-special|MassMessage}}', + 'massmessage-desc' => '{{desc|name=MassMessage|url=https://www.mediawiki.org/wiki/Extension:MassMessage}}', + 'massmessage-sender' => 'Username of the account which sends out messages.', + 'massmessage-form-spamlist' => 'Label for an inputbox on the special page.', + 'massmessage-form-subject' => 'Label for an inputbox on the special page.', + 'massmessage-form-message' => 'Label for an inputbox on the special page.', + 'massmessage-form-global' => 'Label for a checkbox on the special page.', + 'massmessage-form-submit' => 'Label for the submit button on the special page.', + 'massmessage-submitted' => 'Confirmation message the user sees after the form is submitted successfully.', + 'massmessage-account-blocked' => 'Error message the user sees if the bot account has been blocked.', + 'massmessage-spamlist-doesnotexist' => 'Error message the user sees if an invalid spamlist is provided.', + 'right-massmessage' => '{{doc-right|massmessage}}', + 'action-massmessage' => '{{doc-action|massmessage}}', + 'right-massmessage-global' => '{{doc-right|massmessage-global}}', + 'log-name-massmessage' => 'Log page title', + 'log-description-massmessage' => 'Log page description', + 'logentry-massmessage-send' => '{{logentry}}' + +); \ No newline at end of file diff --git a/MassMessage.php b/MassMessage.php new file mode 100644 index 0000000..1752a90 --- /dev/null +++ b/MassMessage.php @@ -0,0 +1,67 @@ +<?php +/* + * Easily send a message to multiple users at once. + * Based on code from TranslationNotifications + * https://mediawiki.org/wiki/Extension:TranslationNotifications + * + * @file + * @ingroup Extensions + * @author Kunal Mehta + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + */ + +// Protect against web entry +if ( !defined( 'MEDIAWIKI' ) ) { + exit; +} + +/* + * Namespaces to extract links for + * + * From your spamlist, only links to these + * domains will be checked. + * Only applies to local messages. + */ +$wgNamespacesToExtractLinksFor = array( NS_PROJECT, NS_USER, NS_USER_TALK ); + +/* + * Namespaces to convert + * + * If you want users to be able to provide a link to a User: page, + * but have the bot post on their User talk: page you can define that here. + * Only applies to local messages. + */ +$wgNamespacesToConvert = array( NS_USER => NS_USER_TALK ); + +/* + * Remote account's password + * + * Only required for global messages. + */ +$wgMassMessageAccountPassword = ''; + + +$wgExtensionCredits[ 'specialpage' ][] = array( + 'path' => __FILE__, + 'name' => 'MassMessage', + 'author' => 'Kunal Mehta', + 'url' => 'https://www.mediawiki.org/wiki/Extension:MassMessage', + 'descriptionmsg' => 'massmessage-desc', + 'version' => '0.0.1', +); + $dir = dirname(__FILE__); + +$wgSpecialPages[ 'MassMessage' ] = 'SpecialMassMessage'; +$wgExtensionMessagesFiles['MassMessage'] = "$dir/MassMessage.i18n.php"; +//$wgExtensionMessagesFiles['MassMessageAlias'] = "$dir/MassMessage.alias.php"; +$wgAutoloadClasses['MassMessage'] = "$dir/MassMessage.body.php"; +$wgAutoloadClasses['SpecialMassMessage'] = "$dir/SpecialMassMessage.php"; +$wgAutoloadClasses['MassMessageJob'] = "$dir/MassMessageJob.php"; +$wgJobClasses['massmessageJob'] = 'MassMessageJob'; + +$wgLogTypes[] = 'massmessage'; +$wgLogActionsHandlers['massmessage/*'] = 'LogFormatter'; +$wgAvailableRights[] = 'massmessage'; // Local messaging +$wgAvailableRights[] = 'massmessage-global'; // Cross-wiki messaging +$wgGroupPermissions['messenger']['massmessage'] = true; +$wgGroupPermissions['sysop']['massmessage'] = true; diff --git a/MassMessageJob.php b/MassMessageJob.php new file mode 100644 index 0000000..d97d1f6 --- /dev/null +++ b/MassMessageJob.php @@ -0,0 +1,100 @@ +<?php +/* + * Job Queue class to send a message to + * a user. + * Based on code from TranslationNotifications + * https://mediawiki.org/wiki/Extension:TranslationNotifications + * + * @file + * @ingroup JobQueue + * @author Kunal Mehta + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + */ +class MassMessageJob extends Job { + public function __construct( $title, $params, $id = 0 ) { + parent::__construct( 'massmessageJob', $title, $params, $id ); + } + + /** + * Execute the job + * + * @return bool + */ + public function run() { + $status = $this->sendLocalMessage(); + + if ( $status !== true ) { + $this->setLastError( $status ); + return false; + } + + return true; + } + /* + * Log any message failures on the submission site. + * + * @param $title Title + * @param $subject string + * @param $reason string + */ + function logLocalFailure( $title, $subject, $reason ) { + + $logEntry = new ManualLogEntry( 'massmessage', 'failure' ); + $logEntry->setPerformer( MassMessage::getMessengerUser() ); + $logEntry->setTarget( $title ); + $logEntry->setComment( $subject ); + $logEntry->setParameters( array( + '4::reason' => $reason, + ) ); + + $logid = $logEntry->insert(); + $logEntry->publish( $logid ); + + } + + /* + * Send a message to a user on the same wiki. + * Modified from the TranslationNotification extension + * + * @return bool + */ + function sendLocalMessage() { + $text = "== " . $this->params['subject'] . " ==\n\n" . $this->params['message']; + + $talkPage = WikiPage::factory( $this->title ); + $flags = $talkPage->checkFlags( 0 ); + if ( $flags & EDIT_UPDATE ) { + $content = $talkPage->getContent( Revision::RAW ); + if ( $content instanceof TextContent ) { + $textContent = $content->getNativeData(); + } else { + // Cannot do anything with non-TextContent pages. Shouldn't happen. + return true; + } + + $text = $textContent . "\n" . $text; + } + + // Check that the sender isn't blocked before we send the message + // This lets a sysop stop the job if needed. + $user = MassMessage::getMessengerUser(); + if ( $user->isBlocked() ) { + // Log it so we know which users didn't get the message. + $this->logLocalFailure( $this->title, $this->params['subject'], 'massmessage-account-blocked' ); + return true; + } + + // Mark the edit as bot + $flags = $flags | EDIT_FORCE_BOT; + + $status = $talkPage->doEditContent( + ContentHandler::makeContent( $text, $this->title ), + $this->params['subject'], + $flags, + false, + $user + ); + + return $status->isGood(); + } +} diff --git a/SpecialMassMessage.php b/SpecialMassMessage.php new file mode 100644 index 0000000..09cd7c7 --- /dev/null +++ b/SpecialMassMessage.php @@ -0,0 +1,168 @@ +<?php + +/* + * Form to allow users to send messages + * to a lot of users at once. + * Based on code from TranslationNotifications + * https://mediawiki.org/wiki/Extension:TranslationNotifications + * + * @file + * @author Kunal Mehta + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + */ + +class SpecialMassMessage extends SpecialPage { + function __construct() { + parent::__construct( 'MassMessage', 'massmessage' ); + } + + function execute( $par ) { + $request = $this->getRequest(); + $output = $this->getOutput(); + $this->setHeaders(); + $this->outputHeader(); + $this->checkPermissions(); + $context = $this->getContext(); + $form = new HtmlForm( $this->createForm(), $context ); + $form->setId( 'massmessage-form' ); + $form->setSubmitText( $context->msg( 'massmessage-form-submit' )->text() ); + $form->setSubmitId( 'massmessage-submit' ); + $form->setSubmitCallback( array( $this, 'submit' ) ); + + $form->prepareForm(); + $result = $form->tryAuthorizedSubmit(); + if ( $result === true || ( $result instanceof Status && $result->isGood() ) ) { + $this->getOutput()->addWikiMsg( 'massmessage-submitted' ); + } elseif ( $result instanceof Status ) { + $errors = $result->getErrorsArray(); + foreach ( $errors as $msg ) { + $this->getOutput()->addWikiMsg( $msg ); + } + } else { + $form->displayForm( $result ); + } + } + + function createForm() { + global $wgUser; + $m = array(); + // Who to send to + $m['spamlist'] = array( + 'id' => 'form-spamlist', + 'type' => 'text', + 'label-message' => 'massmessage-form-spamlist' + ); + // The subject line + $m['subject'] = array( + 'id' => 'form-subject', + 'type' => 'text', + 'label-message' => 'massmessage-form-subject' + ); + + // The message to send + $m['message'] = array( + 'id' => 'form-message', + 'type' => 'textarea', + 'label-message' => 'massmessage-form-message' + ); + + if ( $wgUser->isAllowed( 'massmessage-global' ) ) { + $m['global'] = array( + 'id' => 'form-global', + 'type' => 'checkbox', + 'label-message' => 'massmessage-form-global' + ); + } + + return $m; + } + + /* + * Get a list of pages to spam + * + * @param $spamlist Title + * @return Array + */ + function getLocalTargets( $spamlist ) { + // Something. + global $wgNamespacesToExtractLinksFor, $wgNamespacesToConvert; + $pageID = $spamlist->getArticleID(); + $namespaces = '(' . implode( ', ', $wgNamespacesToExtractLinksFor ) . ')'; + $dbr = wfGetDB( DB_SLAVE ); + $res = $dbr->select( + 'pagelinks', + array( 'pl_namespace', 'pl_title' ), + array( "pl_from=$pageID", "pl_namespace in $namespaces" ), + __METHOD__, + array() + ); + $pages = array(); + foreach ( $res as $row ) { + $ns = $row->pl_namespace; + if ( isset( $wgNamespacesToConvert[$ns] ) ) { + $ns = $wgNamespacesToConvert[$ns]; + } + $pages[] = Title::makeTitle( $ns, $row->pl_title ); + } + return $pages; + } + /* + * Log the spamming to Special:Log/massmessage + * + * @param $spamlist Title + * @param $subject string + */ + function logToWiki( $spamlist, $subject ) { + global $wgUser; + // $title->getLatestRevID() + + $logEntry = new ManualLogEntry( 'massmessage', 'send' ); + $logEntry->setPerformer( $wgUser ); + $logEntry->setTarget( $spamlist ); + $logEntry->setComment( $subject ); + + $logid = $logEntry->insert(); + $logEntry->publish( $logid ); + + } + + /* + * Send out the message + * + * @param $data Array + * @return Status + */ + function submit( $data ) { + // Check that the spamlist exists. + $spamlist = Title::newFromText( $data['spamlist'] ); + $global = $data['global']; // If the message delivery is global + $status = new Status(); + $errors = array(); + if ( $spamlist->getArticleID() == 0 ) { + $status->fatal( 'massmessage-spamlist-doesnotexist' ); + } + + // Check that our account hasn't been blocked. + $user = MassMessage::getMessengerUser(); + if ( !$global && $user->isBlocked() ) { + // If our delivery is global, it doesnt matter if our local account is blocked + $status->fatal( 'massmessage-account-blocked' ); + } + + // If we have any errors, abort. + if ( !$status->isOK() ) { + return $status; + } + + // Log it. + $this->logToWiki( $spamlist, $data['subject'] ); + + // Insert it into the job queue. + $pages = $this->getLocalTargets( $spamlist ); + foreach ( $pages as $page ) { + $job = new MassMessageJob( $page, $data ); + JobQueueGroup::singleton()->push( $job ); + } + return $status; + } +} \ No newline at end of file -- To view, visit https://gerrit.wikimedia.org/r/74831 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I8566b7c13aca7ffa03cf443debd9a52923d04c69 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/MassMessage Gerrit-Branch: master Gerrit-Owner: Legoktm <legoktm.wikipe...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits