Compare commits

...

129 Commits

Author SHA1 Message Date
TehKittyCat d81d1e6cd1 IP range block user is provided as a string. (#77) 2026-02-06 21:12:16 +00:00
Jayden Bailey 342cb911a1 Do not ever send messages for autocreated temp users 2026-02-06 17:08:13 +00:00
translatewiki.net 23965c4b28 Localisation updates from https://translatewiki.net. 2026-02-02 13:12:43 +01:00
translatewiki.net 7bce8b2218 Localisation updates from https://translatewiki.net. 2026-01-26 13:12:07 +01:00
translatewiki.net cd41b8661d Localisation updates from https://translatewiki.net. 2026-01-19 13:12:10 +01:00
translatewiki.net 19cd1e778b Localisation updates from https://translatewiki.net. 2026-01-15 13:12:51 +01:00
translatewiki.net e5ec85956b Localisation updates from https://translatewiki.net. 2026-01-12 13:12:22 +01:00
Jayden Bailey 9337f420cf Move message sending to its own service and use MultiHttpClient
Also removes option to use file_get_contents instead.

This commit should help prepare for future changes to deal with #48.
2026-01-09 19:12:28 +00:00
Jayden Bailey 91f04aa76a Update README with hooks changes 2026-01-09 18:00:34 +00:00
Jayden Bailey ed99a8dddd Rename messages to something sane rather than named after hooks
This will be a breaking change for anyone that has changed these messages on their wiki, unfortunately, but it will make maintaining the extension more sustainable longer term when the hook names change.
2026-01-09 17:57:16 +00:00
Jayden Bailey 55e4e85ecf Add separate message for partial blocks 2026-01-09 17:44:52 +00:00
Jayden Bailey 46837a7493 Update for modern MW code conventions and hook handling 2026-01-09 17:36:06 +00:00
Luka Simić d18d2db7e4 Fixes for MediaWiki 1.44 (#73)
* fix for mediawiki 1.44

* Fix undeletions and moves on 1.44.

* Bump version requirement to MediaWiki 1.40.

---------

Co-authored-by: Friz64 <friz64@protonmail.com>
2026-01-09 15:55:38 +00:00
Luka Simić 5504d01903 Fix PageMoveComplete hook name. (#74) 2025-11-24 17:54:00 +00:00
translatewiki.net 298106ece1 Localisation updates from https://translatewiki.net. 2025-11-24 13:12:34 +01:00
translatewiki.net 5fcb539889 Localisation updates from https://translatewiki.net. 2025-11-10 13:21:45 +01:00
translatewiki.net cf837f82aa Localisation updates from https://translatewiki.net. 2025-10-16 14:16:27 +02:00
translatewiki.net c2f1cee62e Localisation updates from https://translatewiki.net. 2025-10-09 14:19:04 +02:00
translatewiki.net e9695888f4 Localisation updates from https://translatewiki.net. 2025-08-28 14:22:22 +02:00
translatewiki.net ae789d15a2 Localisation updates from https://translatewiki.net. 2025-08-14 14:12:29 +02:00
translatewiki.net a63eaf3a85 Localisation updates from https://translatewiki.net. 2025-06-30 14:11:11 +02:00
pixequil c575f015b3 update PageDeleteComplete hookName (#70)
hadn't been updated when the hook was renamed; results in no emoji rendering
2025-06-25 19:53:11 +01:00
alistair3149 07e1d5b94d Update Block class in onUnblockUserComplete (#69)
Fix Special:Unblock TypeError: DiscordHooks::onUnblockUserComplete(): Argument #1 ($block) must be of type Block, MediaWiki\Block\DatabaseBlock given, called in /var/www/mediawiki/includes/HookContainer/HookContainer.php on line 159
2025-05-19 18:10:01 +01:00
translatewiki.net 27332b8fc6 Localisation updates from https://translatewiki.net. 2025-05-19 14:11:19 +02:00
translatewiki.net 1313b1b318 Localisation updates from https://translatewiki.net. 2025-04-10 14:11:37 +02:00
translatewiki.net 1ba60e4275 Localisation updates from https://translatewiki.net. 2025-04-07 14:10:27 +02:00
translatewiki.net 61c91ef4c8 Localisation updates from https://translatewiki.net. 2024-10-14 14:11:37 +02:00
alistair3149 094c9943ad Update block class (#64)
* Update block class

Fix: #63

* Bump minimum MW requirement to 1.39.0

Have to bump it because 1.38 has no databaseblock class
2024-09-12 17:41:58 +01:00
Dav999 9d14b12829 Use content language instead of user language (#62)
This extension translates the webhook messages according to the UI
language of the user who is making the change. This may not always be
correct - the wiki I edit and the connected Discord server are fully
in English, but since I have the wiki's interface language set to my
native language, the webhook messages were being sent with the
translations hard-baked into them to an English-speaking community.

This commit adds ->inContentLanguage() to all the wfMessage()s so the
webhook messages will be in the same language as the wiki content.
(See https://www.mediawiki.org/wiki/Manual:Messages_API#Language)
2024-09-09 17:24:41 +01:00
translatewiki.net bd74a3a6d9 Localisation updates from https://translatewiki.net. 2024-08-22 14:13:32 +02:00
pppery 67b73e8807 Update link to Meta help (#61) 2024-07-30 22:05:36 +01:00
translatewiki.net 799a5f8462 Localisation updates from https://translatewiki.net. 2024-07-29 14:13:33 +02:00
translatewiki.net 6fca3ad4fe Localisation updates from https://translatewiki.net. 2024-05-06 14:11:05 +02:00
translatewiki.net e5a0efb4c9 Localisation updates from https://translatewiki.net. 2024-02-26 13:13:14 +01:00
Jayden a5de5c323d Merge pull request #58 from ProbablePrime/patch-1
fix(discord): use correct hookname for PageSaveComplete
2024-01-20 02:11:33 +00:00
Jayden 1245a68286 Merge pull request #59 from ProbablePrime/patch-2
docs(settings): clarify array types and add namespace examples
2024-01-20 02:11:14 +00:00
ProbablePrime e3a356c430 docs(settings): clarify array types and add namespace examples
I was very confused configuring this extension and from: #53 it seems better documentation was needed. This adds that :)
2024-01-18 21:29:27 -08:00
ProbablePrime 02044f2ca0 fix(discord): use correct hookname for PageSaveComplete
fixes: #57
2024-01-18 01:22:44 -08:00
translatewiki.net 7b1504bc67 Localisation updates from https://translatewiki.net. 2023-12-21 13:12:44 +01:00
translatewiki.net c9d3370afa Localisation updates from https://translatewiki.net. 2023-12-18 13:15:21 +01:00
translatewiki.net 1ae6d2505d Localisation updates from https://translatewiki.net. 2023-12-14 13:11:22 +01:00
translatewiki.net 818134780c Localisation updates from https://translatewiki.net. 2023-12-04 13:17:46 +01:00
translatewiki.net 4d52fa4644 Localisation updates from https://translatewiki.net. 2023-11-30 13:13:32 +01:00
translatewiki.net 2ddb00328b Localisation updates from https://translatewiki.net. 2023-08-28 13:19:46 +02:00
translatewiki.net ffcce02ffb Localisation updates from https://translatewiki.net. 2023-08-14 13:15:39 +02:00
translatewiki.net 266c428f6f Localisation updates from https://translatewiki.net. 2023-08-10 13:20:51 +02:00
translatewiki.net 58da9dad15 Localisation updates from https://translatewiki.net. 2023-08-07 13:13:15 +02:00
translatewiki.net 812cb525f3 Localisation updates from https://translatewiki.net. 2023-07-31 13:15:43 +02:00
Jayden Bailey f30ebb0ad5 Add redirect fixer user to disabled users by default
See also: https://www.mediawiki.org/wiki/Manual:FixDoubleRedirects.php
2023-07-30 18:16:05 +01:00
translatewiki.net 87546624e2 Localisation updates from https://translatewiki.net. 2023-07-13 13:14:29 +02:00
translatewiki.net 72fee10f32 Localisation updates from https://translatewiki.net. 2023-06-29 13:14:22 +02:00
translatewiki.net 60604ddb6b Localisation updates from https://translatewiki.net. 2023-06-19 13:09:38 +02:00
translatewiki.net 54a2b84a0e Localisation updates from https://translatewiki.net. 2023-06-15 13:23:01 +02:00
translatewiki.net 52e578dc13 Localisation updates from https://translatewiki.net. 2023-06-12 13:20:35 +02:00
translatewiki.net d7b2fcf9d3 Localisation updates from https://translatewiki.net. 2023-06-08 13:09:38 +02:00
Jayden Bailey cd8f91388a Update README.md 2023-06-06 05:14:35 +01:00
Jayden Bailey 6c44fdeaf1 Define user_abbr variable earlier
Fixes #51
2023-06-06 04:30:04 +01:00
translatewiki.net 6b138edf84 Localisation updates from https://translatewiki.net. 2023-06-05 13:09:26 +02:00
translatewiki.net 367d50494b Localisation updates from https://translatewiki.net. 2023-06-01 13:12:12 +02:00
Jayden Bailey 83e505d39b Add missing emoji for RenameUserComplete 2023-05-19 02:22:22 +01:00
Jayden Bailey 5bdc31f6e8 Replace deprecated ArticleDeleteComplete hook and fix some incorrect emojis 2023-05-19 02:19:28 +01:00
Jayden Bailey 42f292f17f Handle UserIdentity being passed to isDisabled function 2023-05-19 02:02:41 +01:00
Jayden Bailey 2a9a65a59a Properly handle UserIdentity objects in createUserLinks and ensure CIDR blocks appear on blocked messages
Fixes #47
2023-05-19 01:52:40 +01:00
Jayden 2a560d9acc Update extension.json 2022-12-19 03:42:48 +00:00
Jayden 0b91e8edc8 Update extension.json 2022-05-25 21:48:40 +01:00
Jayden Bailey 96070a6538 Update to support MediaWiki 1.38. Use UserFactory for creating User objects from UserIdentity. 2022-05-23 15:04:36 +01:00
Jayden Bailey 80f28e5920 Do not parse any Discord mentions in webhook messages
Resolves #42, closes #41
2022-04-18 21:08:32 +01:00
Jayden Bailey 27d39a9d4a Add support for the Renameuser extension 2021-11-29 19:18:49 +00:00
Jayden e5b1669d53 Merge pull request #39 from TehKittyCat/fixes
Fix Diff Links
2021-11-22 11:56:40 +00:00
TehKittyCat d3c49f1123 Fix broken diff link. 2021-11-22 02:43:27 -05:00
TehKittyCat 5ea635fd9a Remove unneeded 'use WikiPage', fixes PHP notice. 2021-11-22 01:47:51 -05:00
Jayden Bailey 4304818bdb Fix another deprecation warning 2021-11-21 18:46:34 +00:00
Jayden Bailey 3fb4b609d4 Update README to indicate new minimum MW requirement 2021-11-17 13:09:37 +00:00
Jayden Bailey 83deddd7ee Merge branch 'TehKittyCat-deprecation-fixes' 2021-11-17 13:08:40 +00:00
Jayden Bailey 160a512d67 Fix removed function call in createRevisionText (1.36+)
This commit raises the requirement of the extension to MediaWiki 1.36.
2021-11-17 13:06:16 +00:00
TehKittyCat f4dc6960bb Replace remaining usage of Revision with RevisionRecord to eliminate MediaWiki 1.36 deprecations and to fix MediaWiki 1.37 compatibility, where it has been removed. 2021-11-17 00:45:17 -05:00
TehKittyCat c24fee7a66 Replace usage of deprecated hooks. PageContentSaveComplete is replaced with PageSaveComplete and TitleMoveComplete is replaced with PageMoveComplete. This extension now requires MediaWiki 1.35 or higher. 2021-11-17 00:21:12 -05:00
TehKittyCat 1e962c55fb Fix "Title::get{Canonical,Full,Link,Local,Internal}URL method called with a second parameter is deprecated since MediaWiki 1.19. Add your parameter to an array passed as the first parameter.", fix function call casing, and use the canonical protocol. 2021-11-16 16:11:31 -05:00
Jayden Bailey 0a6992b13b Update README 2021-10-19 14:20:41 +01:00
Jayden Bailey 95567934b0 Remove composer.json. I don't use unit tests here. 2021-10-19 14:06:10 +01:00
Jayden 5e04b3afda Merge pull request #36 from dodocodes/patch-2
Update README.md
2021-09-14 02:55:52 +01:00
Jayden 91610c72fd Update README.md 2021-09-14 02:55:40 +01:00
Jayden f1cae6b097 Merge pull request #35 from DesignerThan95/patch-1
Update extension.json - added missing colon
2021-09-14 02:55:08 +01:00
DodoCodes.com 1a9cbbf48f Update README.md
Added instructions for installing missing dependencies.
2021-09-12 18:16:38 -07:00
DesignerThan df0b14017b Update extension.json - added missing colon 2021-08-17 23:38:05 +02:00
Jayden Bailey ffc78324ff Fix bug with preg_replace for username truncating and change truncation to be configurable 2021-05-04 17:27:34 +01:00
Jayden Bailey 5a303252e3 Merge branch 'master' of github.com:jaydenkieran/mw-discord 2021-05-04 17:02:24 +01:00
Jayden Bailey 4ec63619f5 Change emojis to be configurable (resolves #25) 2021-05-04 17:00:55 +01:00
Jayden Bailey 572d9e3d87 Sanitise summary/reason text input (closes #13) 2021-05-04 17:00:47 +01:00
Jayden Bailey 3eb34310ef Merge pull request #33 from Joeytje50/patch-1
Abbreviate anyone with a name longer than 25 chars
2021-05-04 16:08:34 +01:00
Joeytje50 7c20f06902 Abbreviate anyone with a name longer than 25 chars
Any username of 25 or more characters will be abbreviated to the first 20 characters, then `...`, and then the last three. This is especially helpful for RC stalkers with discord taking up only half their screen.

Different ways to abbreviate names would be possible by changing the regex pattern's numbers, or the resulting string.
2021-04-23 17:13:11 +02:00
Jayden Bailey 144499a248 Update README with branch/install info 2020-09-18 14:58:28 +01:00
Jayden Bailey 079e688ee9 Fix fatal error when blocking users
Fixes #27, closes #29
2020-09-18 14:51:07 +01:00
Jayden Bailey fb6e0f7755 Update README file 2020-06-12 16:02:35 +01:00
Jayden Bailey 4e17d17de6 Add emojis config option 2020-06-12 16:00:01 +01:00
Jayden Bailey f3b2531380 Support Approved Revs hooks
Closes #24
2020-06-12 15:36:15 +01:00
Jayden Bailey 536a4afe13 Support ArticleMergeComplete hook
Closes #16
2020-06-12 14:22:16 +01:00
Jayden Bailey b3648a462c Use RequestContext instead of wgUser
Closes #9
2019-11-23 11:48:21 +00:00
Jayden Bailey bbff717a24 Add extra debug log message 2019-11-23 09:55:16 +00:00
Jayden Bailey 6d8b2c33cb Add Content-Type header for curl requests 2019-11-23 09:53:09 +00:00
Jayden Bailey 47eef3c35d Small fix for error message 2019-11-23 09:00:24 +00:00
Jayden Bailey 7f51c4f310 Update README 2019-07-24 12:29:13 +01:00
Jayden Bailey ad101a326f Send messages for Special:Import
Fixes #6
2019-07-24 12:26:46 +01:00
Jayden Bailey 687d1abf1f Update project README file 2019-07-19 17:03:26 +01:00
Jayden Bailey 0df5463a87 Bump extension version 2019-07-19 16:59:04 +01:00
Jayden Bailey 10b4db72f7 Link directly to contribs page when user is anonymous
Resolves #12
2019-07-19 16:58:41 +01:00
Jayden Bailey fb9ada8f9c Drop cURL timeout down to 10 seconds incase of Discord downtime 2019-07-19 16:40:20 +01:00
Jayden Bailey 9a7dd03d5c Add option for using file_get_contents
Resolves #14
2019-07-19 16:39:38 +01:00
Jayden Bailey fa9149165d Bump version and update readme 2019-06-16 13:39:56 +01:00
Jayden Bailey ca3a5f8047 Add option to include timestamps on messages
Closes #11
2019-06-16 13:38:15 +01:00
Jayden Bailey 591ef8746e Merge pull request #8 from Dinoguy1000/patch-2
consistently suppress bot actions...
2019-05-13 18:33:47 +01:00
Dinoguy1000 6c2e30deab bump version number too 2019-04-30 19:28:29 -05:00
Dinoguy1000 ce780adf10 Update DiscordHooks.php 2019-04-30 19:22:35 -05:00
Jayden Bailey 680040e823 Merge pull request #3 from Railfail536/patch-1
Add Polish i18n
2019-05-01 01:20:57 +01:00
Jayden Bailey 8fa8dce03d Merge pull request #7 from Dinoguy1000/patch-1
default to revision size for diff size
2019-05-01 01:14:21 +01:00
Dinoguy1000 c3bdbecee5 consistently suppress bot actions...
...when $wgDiscordNoBots is true. This prevents (un)deletions, (un)protections, and file uploads from being reported when performed by a bot. Also did a bit of globals cleanup in one function.
2019-04-29 15:05:53 -05:00
Dinoguy1000 6ccca7b823 default to revision size for diff size
Certain events (primarily page creations) fail to display a diff size because there effectively is no diff (there is no previous revision to diff with); in these cases, just display the size of the current revision.
2019-04-29 14:52:52 -05:00
Jayden Bailey 03d612a3f7 handle potential strings in createUserLinks 2019-04-24 11:11:00 +01:00
Jayden Bailey 9830df7e97 Merge pull request #5 from xunto/xunto-patch-2
Fix unneeded broken curl_exec (Unknown Error with Visual Editor)
2019-01-29 22:16:11 +00:00
Orlov Valentine cecb90dffc Fix unneeded broken curl_exec 2019-01-30 00:44:53 +03:00
Jayden Bailey 9034275470 Update extension.json 2019-01-29 13:33:50 +00:00
Jayden Bailey 3f1e1e784b Add different message for page creations
Closes #4
2019-01-29 13:32:40 +00:00
Rail 78d66e5e31 + pl.json 2019-01-28 12:19:52 +01:00
Jayden Bailey f0cf5a741d fix substitution on remaining hooks 2019-01-24 16:51:05 +00:00
Jayden Bailey c193c24be2 better checks for file namespace 2019-01-22 16:22:26 +00:00
Jayden Bailey 4b46212f49 stop substitution for edit summaries 2019-01-22 16:02:28 +00:00
Jayden Bailey d6d0f22c01 Add wgDiscordDisabledUsers, closes #1 2018-12-30 21:14:07 +00:00
Jayden Bailey 0cf579aa6a Add DiscordMaxChars 2018-12-16 21:12:13 +00:00
Jayden Bailey ac38da8529 remove defunct tests 2018-12-16 20:49:24 +00:00
39 changed files with 2006 additions and 523 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
/vendor/
debug.log
debug.log
.DS_Store
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018 Jayden Bailey
Copyright (c) 2021 Jayden Bailey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+41 -16
View File
@@ -1,7 +1,7 @@
# Discord (mw-discord)
MediaWiki extension for sending notifications to a Discord webhook from MediaWiki. When a certain event occurs on your MediaWiki wiki, including new edits, they can be sent as a message to a channel on a Discord server using a webhook.
Multiple webhook URLs are supported and messages will be sent to all of them using cURL, so your web server is required to have cURL installed (for most Linux distros, installing using `sudo apt install curl` should work).
Multiple webhook URLs are supported and messages will be sent to all of them.
**Live demo**: https://runescape.wiki (https://discord.gg/runescapewiki)
@@ -10,13 +10,16 @@ Multiple webhook URLs are supported and messages will be sent to all of them usi
</p>
## Requirements
- **Discord webhook URL**: This can be obtained by editing a channel on a server with the correct permissions.
- **MediaWiki 1.31+**
- **cURL**
- **Discord webhook URL**: Found by editing a channel -> Integrations -> Webhooks
- **MediaWiki**: This extension aims to always support the [latest LTS release](https://www.mediawiki.org/wiki/Version_lifecycle).
- Use the branch that is equal to, or below your current version.
- We do not support versions of MediaWiki that are considered end-of-life.
- The `master` branch may contain changes that are only applicable to the current alpha version of MediaWiki.
- **[cURL](https://www.php.net/curl)** (likely installed already). Without this, the extension may still work, but requests will be sent inefficiently.
## Installation
1. Clone this repository to your MediaWiki installation's `extensions` folder using `git clone https://github.com/jaydenkieran/mw-discord.git Discord`
1. Clone this repository to your MediaWiki installation's `extensions` folder using `git clone https://github.com/jaydenkieran/mw-discord.git -b REL1_35 Discord`
2. Modify your `LocalSettings.php` file and add:
```php
@@ -39,22 +42,30 @@ This extension can be configured using the `LocalSettings.php` file in your Medi
| `$wgDiscordWebhookURL` | string/array | Discord webhook URLs
### Optional
These parameters aren't required for the extension to work.
| Variable | Type | Description | Default |
| --- | --- | --- | --- |
| `$wgDiscordNoBots` | bool | Do not send notifications that are triggered by a [bot account](https://www.mediawiki.org/wiki/Manual:Bots) | `true`
| `$wgDiscordNoMinor` | bool | Do not send notifications that are for [minor edits](https://meta.wikimedia.org/wiki/Help:Minor_edit) | `false`
| `$wgDiscordNoMinor` | bool | Do not send notifications that are for [minor edits](https://www.mediawiki.org/wiki/Help:Minor_edit) | `false`
| `$wgDiscordNoNull` | bool | Do not send notifications for [null edits](https://www.mediawiki.org/wiki/Manual:Purge#Null_edits) | `true`
| `$wgDiscordSuppressPreviews` | bool | Force previews for links in Discord messages to be suppressed | `true`
| `$wgDiscordDisabledHooks` | array | List of hooks to disable sending webhooks for (see [below](#hooks-used)) | `[]`
| `$wgDiscordDisabledNS` | array | List of namespaces to disable sending webhooks for (see [below](#hooks-used)) | `[]`
| `$wgDiscordMaxChars` | int | Maximum amount of characters for user-generated text (e.g summaries, reasons). Set to `null` to disable truncation | `null`
| `$wgDiscordMaxCharsUsernames` | int | Maximum amount of characters for usernames. Set to `null` to disable truncation | `25`
| `$wgDiscordDisabledHooks` | string array | List of hooks to disable sending webhooks for (see [below](#hooks-used)) | `[]`
| `$wgDiscordDisabledNS` | int array | List of namespace **IDs** to disable sending webhooks for. (see [below](#namespaces)) | `[]`
| `$wgDiscordDisabledUsers` | string array | List of users whose performed actions shouldn't send webhooks | `[]`
| `$wgDiscordPrependTimestamp` | bool | Prepend a timestamp (in UTC) to all sent messages. The format can be changed by editing the MediaWiki message `discord-timestampformat` | `false`
| `$wgDiscordUseEmojis` | bool | Prepend emojis to different types of messages to help distinguish them | `false`
| `$wgDiscordEmojis` | string associative array | Map of hook names and their associated emojis to prepend to messages if `$wgDiscordUseEmojis` is enabled | See [extension.json](/extension.json#L30)
## Hooks used
- `PageContentSaveComplete` - New edits to pages and page creations
- `ArticleDeleteComplete` - Page deletions
- `ArticleUndelete` - Page restorations
- `PageSaveComplete` - New edits to pages and page creations
- `PageDeleteComplete` - Page deletions
- `PageUndeleteComplete` - Page restorations
- `ArticleRevisionVisibilitySet` - Revision visibility changes
- `ArticleProtectComplete` - Page protections
- `TitleMoveComplete` - Page moves
- `PageMoveComplete` - Page moves
- `LocalUserCreated` - User registrations
- `BlockIpComplete` - User blocked
- `UnblockUserComplete` - User unblocked
@@ -62,11 +73,25 @@ This extension can be configured using the `LocalSettings.php` file in your Medi
- `UploadComplete` - File was uploaded
- `FileDeleteComplete` - File revision was deleted
- `FileUndeleteComplete` - File revision was restored
- `AfterImportPage` - Page was imported
- `ArticleMergeComplete` - Article histories were merged
- `RenameUserComplete` - Rename was completed
### [Approved Revs](https://www.mediawiki.org/wiki/Extension:Approved_Revs)
- `ApprovedRevsRevisionApproved` - Revision was approved
- `ApprovedRevsRevisionUnapproved` - Revision was unapproved
- `ApprovedRevsFileRevisionApproved` - File revision was approved
- `ApprovedRevsFileRevisionUnapproved` - File revision was unapproved
## Namespaces
As we use namespace IDs the following resources might be helpful:
- [Built in namespaces' IDs](https://www.mediawiki.org/wiki/Manual:Namespace#Built-in_namespaces)
- [Extension default namespaces](https://www.mediawiki.org/wiki/Extension_default_namespaces)
## Translation
This extension can be translated through the messages in the `ì18n` folder if you're a developer. As a wiki administrator, you may find it a better option to edit the messages on-site in the MediaWiki namespace.
Any excess whitespace in text that is translated will be stripped (e.g double spaces, etc).
You can submit translations for this extension on [Translatewiki.net](https://translatewiki.net/wiki/Special:Translate/mwgithub-mw-discord).
## License
This extension is licensed under the MIT License, [see here](LICENSE) for more information. This project is originally inspired by Szmyk's [mediawiki-discord](https://github.com/Szmyk/mediawiki-discord) project, but has been rewritten completely to be more suitable for my needs.
This extension is available under the MIT license. You can [see here](LICENSE) for more information.
This extension was inspired by Szmyk's [mediawiki-discord](https://github.com/Szmyk/mediawiki-discord) project.
-5
View File
@@ -1,5 +0,0 @@
{
"require": {
"phpunit/phpunit": "4.8.*"
}
}
+70 -21
View File
@@ -1,12 +1,15 @@
{
"name": "Discord",
"author": [
"[https://github.com/jaydenkieran Jayden Bailey]"
"[https://github.com/jayktaylor Jayden Bailey]"
],
"url": "https://github.com/jaydenkieran/mw-discord",
"version": "1.0",
"url": "https://github.com/jayktaylor/mw-discord",
"version": "1.2",
"descriptionmsg": "discord-desc",
"license-name": "MIT",
"requires": {
"MediaWiki": ">= 1.40.0"
},
"manifest_version": 1,
"config": {
"DiscordWebhookURL": [],
@@ -14,29 +17,75 @@
"DiscordNoMinor": false,
"DiscordNoNull": true,
"DiscordSuppressPreviews": true,
"DiscordMaxChars": null,
"DiscordMaxCharsUsernames": 25,
"DiscordDisabledHooks": [],
"DiscordDisabledNS": []
"DiscordDisabledNS": [],
"DiscordDisabledUsers": [
"Redirect fixer"
],
"DiscordPrependTimestamp": false,
"DiscordUseEmojis": false,
"DiscordEmojis": {
"PageSaveComplete": ":pencil2:",
"PageDeleteComplete": ":wastebasket:",
"PageUndeleteComplete": ":wastebasket:",
"ArticleRevisionVisibilitySet": ":spy:",
"ArticleProtectComplete": ":lock:",
"PageMoveComplete": ":truck:",
"LocalUserCreated": ":wave:",
"BlockIpComplete": ":no_entry_sign:",
"UnblockUserComplete": ":no_entry_sign:",
"UserGroupsChanged": ":people_holding_hands:",
"UploadComplete": ":inbox_tray:",
"FileDeleteComplete": ":wastebasket:",
"FileUndeleteComplete": ":wastebasket:",
"AfterImportPage": ":books:",
"ArticleMergeComplete": ":card_box:",
"ApprovedRevsRevisionApproved": ":white_check_mark:",
"ApprovedRevsRevisionUnapproved": ":white_check_mark:",
"ApprovedRevsFileRevisionApproved": ":white_check_mark:",
"ApprovedRevsFileRevisionUnapproved": ":white_check_mark:",
"RenameUserComplete": ":people_holding_hands:"
}
},
"AutoloadClasses": {
"DiscordHooks": "src/DiscordHooks.php",
"DiscordUtils": "src/Utils.php"
"AutoloadNamespaces": {
"MediaWiki\\Extension\\Discord\\": "src/"
},
"MessagesDirs": {
"mw-discord": "i18n"
},
"HookHandlers": {
"main": {
"class": "MediaWiki\\Extension\\Discord\\DiscordHooks",
"services": [
"Discord.DiscordMessageSender"
]
}
},
"Hooks": {
"PageContentSaveComplete": "DiscordHooks::onPageContentSaveComplete",
"ArticleDeleteComplete": "DiscordHooks::onArticleDeleteComplete",
"ArticleUndelete": "DiscordHooks::onArticleUndelete",
"ArticleRevisionVisibilitySet": "DiscordHooks::onArticleRevisionVisibilitySet",
"ArticleProtectComplete": "DiscordHooks::onArticleProtectComplete",
"TitleMoveComplete": "DiscordHooks::onTitleMoveComplete",
"LocalUserCreated": "DiscordHooks::onLocalUserCreated",
"BlockIpComplete": "DiscordHooks::onBlockIpComplete",
"UnblockUserComplete": "DiscordHooks::onUnblockUserComplete",
"UserGroupsChanged": "DiscordHooks::onUserGroupsChanged",
"UploadComplete": "DiscordHooks::onUploadComplete",
"FileDeleteComplete": "DiscordHooks::onFileDeleteComplete",
"FileUndeleteComplete": "DiscordHooks::onFileUndeleteComplete"
}
"PageSaveComplete": "main",
"PageDeleteComplete": "main",
"PageUndeleteComplete": "main",
"ArticleRevisionVisibilitySet": "main",
"ArticleProtectComplete": "main",
"PageMoveComplete": "main",
"LocalUserCreated": "main",
"BlockIpComplete": "main",
"UnblockUserComplete": "main",
"UserGroupsChanged": "main",
"UploadComplete": "main",
"FileDeleteComplete": "main",
"FileUndeleteComplete": "main",
"AfterImportPage": "main",
"ArticleMergeComplete": "main",
"ApprovedRevsRevisionApproved": "main",
"ApprovedRevsRevisionUnapproved": "main",
"ApprovedRevsFileRevisionApproved": "main",
"ApprovedRevsFileRevisionUnapproved": "main",
"RenameUserComplete": "main"
},
"ServiceWiringFiles": [
"src/ServiceWiring.php"
]
}
+36
View File
@@ -0,0 +1,36 @@
{
"@metadata": {
"authors": [
"Asma",
"Mohammed Qays"
]
},
"discord-desc": "يرسل رسائل إلى قناة Discord عند وقوع أحداث معينة",
"discord-talk": "ت",
"discord-contribs": "ج",
"discord-diff": "فرق",
"discord-minor": "(م)",
"discord-msg-page-edited": "قام $1 بإنشاء $2 $3 $4",
"discord-msg-page-created": "قام $1 بإنشاء $2 $3 $4",
"discord-msg-page-deleted": "تم حذف $1 $2 $3 (تم حذف $4 من المراجعات)",
"discord-msg-page-undeleted-revs": "المراجعات لـ",
"discord-msg-page-undeleted": "$1 قام بإلغاء حذف $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 غيرت رؤية $2 من المراجعات على $3",
"discord-msg-page-protect": "$1 تم تغييره لحماية $2 $3 ( $4 )",
"discord-msg-page-moved": "قام $1 بنقل من $2 إلى $3 $4 $5",
"discord-msg-user-registered": "تم تسجيل $1",
"discord-msg-user-block": "$1 منع $2 $3 ($4)",
"discord-msg-user-unblock": "$1 قام بإلغاء منع $2",
"discord-msg-user-groups-changed": "$1 غير حقوق $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "إصدار جديد من",
"discord-msg-file-upload": "قام $1 بتحميل $2 $3 $4 ($5، $6×$7 ،$8)",
"discord-msg-file-delete": "قام $1 بحذف نسخة من الملف $2 $3",
"discord-msg-file-undelete": "استعاد $1 بعض إصدارات الملف $2 $3",
"discord-msg-import": "قام $1 باستيراد $2 (تم استيراد مراجعات $4 / $3)",
"discord-msg-page-merge": "دمج $1 المراجعات من $2 إلى $3",
"discord-msg-ext-approvedrevs-approved": "وافق $1 على مراجعة جديدة بقيمة $2 (المراجعة $3) من المستخدم $4",
"discord-msg-ext-approvedrevs-unapproved": "لم يوافق $1 على مراجعة الملف المعتمدة لـ $2",
"discord-msg-ext-approvedrevs-approved-file": "وافق $1 على مراجعة ملف جديد بقيمة $2 ($3) من المستخدم $4",
"discord-msg-ext-approvedrevs-unapproved-file": "لم يوافق $1 على مراجعة الملف المعتمدة لـ $2",
"discord-msg-user-rename": "أعاد $1 تسمية المستخدم $2 إلى $3"
}
+15
View File
@@ -0,0 +1,15 @@
{
"@metadata": {
"authors": [
"আফতাবুজ্জামান"
]
},
"discord-talk": "আ",
"discord-contribs": "অ",
"discord-diff": "পার্থক্য",
"discord-minor": "(অ)",
"discord-msg-page-edited": "$1 $2 সম্পাদনা করেছেন $3 $4",
"discord-msg-page-created": "$1 $2 তৈরি করেছেন $3 $4",
"discord-msg-user-registered": "$1 নিবন্ধিত হয়েছে",
"discord-msg-user-block": "$1 $2-কে বাধা দিয়েছেন $3 ($4)"
}
+35
View File
@@ -0,0 +1,35 @@
{
"@metadata": {
"authors": [
"Умар"
]
},
"discord-desc": "Цхьацца хиламаш хилча, Discord канале хаамаш дӀакхачабо.",
"discord-talk": "д",
"discord-contribs": "c",
"discord-diff": "башха",
"discord-minor": "(m)",
"discord-msg-page-edited": "$1 хийцам бина $2 $3 $4",
"discord-msg-page-created": "$1 кхоьллина $2 $3 $4",
"discord-msg-page-deleted": "$1 дӀайаьккхина $2 $3 ($4 версеш дӀайаьхна)",
"discord-msg-page-undeleted-revs": "версеш",
"discord-msg-page-undeleted": "$1 меттахӀоттийна $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 хийцина $2 версин гуш хилар $3 тӀе",
"discord-msg-page-protect": "$1 хийцина ларйар $2 $3 ($4)",
"discord-msg-page-moved": "$1 дехьайаьккхина $2 тӀе $3 $4 $5.",
"discord-msg-user-registered": "$1 регистраци йина",
"discord-msg-user-block": "$1 блоктоьхна $2 $3 ($4)",
"discord-msg-user-unblock": "$1 блокдӀайаьккхина $2",
"discord-msg-user-groups-changed": "$1 бакъонаш хийцина $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "керла верси",
"discord-msg-file-upload": "$1 чуйаьккхина $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 дӀайаьккхина файлан верси $2 $3",
"discord-msg-file-undelete": "$1 меттахӀоттийна цхьайолу версеш файлан $2 $3",
"discord-msg-import": "$1 импорт йина $2 (импорт йина $4/$3 версеш)",
"discord-msg-page-merge": "$1 цхьаьнатоьхна версеш $2 - $3",
"discord-msg-ext-approvedrevs-approved": "$1 тӀечӀагӀйина керла верси $2 (верси $3) декъашхочун $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 тӀечӀагӀйина верси $2 тӀе ца эцна",
"discord-msg-ext-approvedrevs-approved-file": "$1 тӀечӀагӀйина $2 ($3) файлан керла верси декъашхочуьнгара $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 тӀе ца эцна $2 файлан тӀечӀагӀйина верси",
"discord-msg-user-rename": "$1 декъашхочун хийцина $2 → $3"
}
+17
View File
@@ -0,0 +1,17 @@
{
"@metadata": {
"authors": [
"Ceirios"
]
},
"discord-desc": "Anfon negeseuon i sianel Discord pan fydd digwyddiadau penodol yn digwydd",
"discord-talk": "s",
"discord-contribs": "c",
"discord-diff": "gwahan",
"discord-minor": "(b)",
"discord-msg-page-edited": "Golygodd $1 $2 $3 $4",
"discord-msg-page-created": "Crëodd $1 $2 $3 $4",
"discord-msg-page-deleted": "Dilëodd $1 $2 $3 (dilëwyd $4 o olygiadau)",
"discord-msg-page-undeleted-revs": "golygiadau ar gyfer",
"discord-msg-page-undeleted": "Adferodd $1 $2 $3 $4"
}
+39
View File
@@ -0,0 +1,39 @@
{
"@metadata": {
"authors": [
"Brettchenweber",
"Fyoouki",
"PretzelRocky",
"TomatoCake"
]
},
"discord-desc": "Sendet Nachrichten an einen Discord-Kanal, wenn bestimmte Ereignisse eintreten",
"discord-talk": "Diskussion",
"discord-contribs": "Beiträge",
"discord-diff": "Unterschied",
"discord-minor": "(K)",
"discord-msg-page-edited": "$1 bearbeitete $2 $3 $4",
"discord-msg-page-created": "$1 erstellte $2 $3 $4",
"discord-msg-page-deleted": "$1 löschte $2 $3 ($4 revisionen gelöscht)",
"discord-msg-page-undeleted-revs": "revisionen für",
"discord-msg-page-undeleted": "$1 hat $2 wiederhergestellt $3 $4",
"discord-msg-rev-visibility-changed": "$1 veränderte die Sichtbarkeit von $2 revisionen auf $3",
"discord-msg-page-protect": "$1 änderte den Schutz von $2 $3 ($4)",
"discord-msg-page-moved": "$1 verschob $2 zu $3 $4 $5",
"discord-msg-user-registered": "$1 hat sich registriert",
"discord-msg-user-block": "$1 blockierte $2 $3 ($4)",
"discord-msg-user-block-partial": "$1 hat $2 teilweise gesperrt $3 ($4)",
"discord-msg-user-unblock": "$1 entsperrte $2",
"discord-msg-user-groups-changed": "$1 hat die Benutzerrechte geändert von $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "neue Version von",
"discord-msg-file-upload": "$1 lud $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 hat eine Version der Datei gelöscht $2 $3",
"discord-msg-file-undelete": "$1 hat eine Version einer Datei wiederhergestellt von $2 $3",
"discord-msg-import": "$1 importierte $2 (Import $4/$3 revisionen)",
"discord-msg-page-merge": "$1 hat die Revisionen von $2 mit $3 zusammengeführt",
"discord-msg-ext-approvedrevs-approved": "$1 genehmigte eine neue Revision von $2 (Revision $3) von $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 hat die genehmigte Revsision von $2 zurückgezogen.",
"discord-msg-ext-approvedrevs-approved-file": "$1 genehmigte eine neue Dateirevision von $2 ($3) durch Benutzer $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 hat die genehmigte Dateirevision von $2 zurückgezogen",
"discord-msg-user-rename": "$1 hat Benutzer von $2 in $3 umbenannt"
}
+35
View File
@@ -0,0 +1,35 @@
{
"@metadata": {
"authors": [
"Dogogos123",
"Norhorn",
"Spyridon Eftychios Kokotos"
]
},
"discord-desc": "Στέλνει μηνύματα σε ένα κανάλι Discord όταν συμβαίνουν ορισμένα συμβάντα",
"discord-diff": "διαφορά",
"discord-minor": "(μ)",
"discord-msg-page-edited": "$1 επεξεργάστηκε $2 $3 $4.",
"discord-msg-page-created": "$1 δημιούργησε $2 $3 $4",
"discord-msg-page-deleted": "$1 διαγράφηκε $2 $3 ($4 αναθεωρήσεις διαγράφηκαν)",
"discord-msg-page-undeleted-revs": "αναθεωρήσεις για",
"discord-msg-page-undeleted": "$1 επανέφερε $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 άλλαξε την ορατότητα των $2 αναθεωρήσεων στο $3",
"discord-msg-page-protect": "$1 άλλαξε προστασία του $2 $3 ($4)",
"discord-msg-page-moved": "$1 μετακίνησε $2 στα $3 $4 $5",
"discord-msg-user-registered": "$1 εγγεγραμμένος",
"discord-msg-user-block": "$1 αποκλεισμένο $2 $3 ($4)",
"discord-msg-user-unblock": "$1 ξεμπλόκαρε $2",
"discord-msg-user-groups-changed": "$1 άλλαξε τα δικαιώματα των $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "νέα έκδοση του",
"discord-msg-file-upload": "$1 μεταφορτώθηκε $2 $3 $4 ( $5 , $6 x $7 , $8 )",
"discord-msg-file-delete": "$1 διέγραψε μια έκδοση του αρχείου $2 $3",
"discord-msg-file-undelete": "$1 επανέφερε ορισμένες εκδόσεις του αρχείου $2 $3",
"discord-msg-import": "$1 εισήχθη $2 (εισαγμένες $4 / $3 αναθεωρήσεις)",
"discord-msg-page-merge": "$1 συγχώνευσε αναθεωρήσεις από $2 σε $3",
"discord-msg-ext-approvedrevs-approved": "$1 ενέκρινε μια νέα αναθεώρηση των $2 (αναθεώρηση $3 ) από τον χρήστη $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 κατάργησε την έγκριση της εγκεκριμένης αναθεώρησης του αρχείου για $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 ενέκρινε μια νέα αναθεώρηση αρχείου $2 ( $3 ) από τον χρήστη $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 κατάργησε την έγκριση της εγκεκριμένης αναθεώρησης του αρχείου για $2",
"discord-msg-user-rename": "$1 μετονόμασε τον χρήστη $2 σε $3"
}
+31 -16
View File
@@ -1,4 +1,9 @@
{
"@metadata": {
"authors": [
"Jayden Bailey"
]
},
"discord-desc": "Sends messages to a Discord channel when certain events occur",
"discord-userlinks": "$1 ($2|$3)",
"discord-revisionlinks": "($1) $2 $3",
@@ -7,20 +12,30 @@
"discord-diff": "diff",
"discord-minor": "(m)",
"discord-size": "($1)",
"discord-edit": "$1 edited $2 $3 $4",
"discord-articledelete": "$1 deleted $2 $3 ($4 revisions deleted)",
"discord-undeleterev": "revisions for",
"discord-articleundelete": "$1 undeleted $2 $3 $4",
"discord-revvisibility": "$1 changed visibility of $2 revisions on $3",
"discord-articleprotect": "$1 changed protection of $2 $3 ($4)",
"discord-titlemove": "$1 moved $2 to $3 $4 $5",
"discord-localusercreated": "$1 registered",
"discord-blocktimeformat": "d F Y H:i",
"discord-blockipcomplete": "$1 blocked $2 $3 ($4)",
"discord-unblockusercomplete": "$1 unblocked $2",
"discord-usergroupschanged": "$1 changed rights of $2 $3 ($4) ($5)",
"discord-uploadnewver": "new version of",
"discord-uploadcomplete": "$1 uploaded $2 $3 $4 ($5, $6x$7, $8)",
"discord-filedeletecomplete": "$1 deleted a version of file $2 $3",
"discord-fileundeletecomplete": "$1 restored some versions of file $2 $3"
"discord-msg-page-edited": "$1 edited $2 $3 $4",
"discord-msg-page-created": "$1 created $2 $3 $4",
"discord-msg-page-deleted": "$1 deleted $2 $3 ($4 revisions deleted)",
"discord-msg-page-undeleted-revs": "revisions for",
"discord-msg-page-undeleted": "$1 undeleted $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 changed visibility of $2 revisions on $3",
"discord-msg-page-protect": "$1 changed protection of $2 $3 ($4)",
"discord-msg-page-moved": "$1 moved $2 to $3 $4 $5",
"discord-msg-user-registered": "$1 registered",
"discord-msg-user-block-timeformat": "d F Y H:i",
"discord-msg-user-block": "$1 blocked $2 $3 ($4)",
"discord-msg-user-block-partial": "$1 partially blocked $2 $3 ($4)",
"discord-msg-user-unblock": "$1 unblocked $2",
"discord-msg-user-groups-changed": "$1 changed rights of $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "new version of",
"discord-msg-file-upload": "$1 uploaded $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 deleted a version of file $2 $3",
"discord-msg-file-undelete": "$1 restored some versions of file $2 $3",
"discord-msg-import": "$1 imported $2 (imported $4/$3 revisions)",
"discord-timestampformat": "**H:i e:**",
"discord-msg-page-merge": "$1 merged revisions from $2 into $3",
"discord-msg-ext-approvedrevs-approved": "$1 approved a new revision of $2 (revision $3) from user $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 unapproved the approved revision for $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 approved a new file revision of $2 ($3) from user $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 unapproved the approved file revision for $2",
"discord-msg-user-rename": "$1 renamed the user $2 to $3"
}
+35
View File
@@ -0,0 +1,35 @@
{
"@metadata": {
"authors": [
"MatyGamingHD"
]
},
"discord-desc": "Envía mensajes a un canal de Discord cuando ocurren ciertos eventos",
"discord-talk": "d",
"discord-contribs": "c",
"discord-diff": "difs",
"discord-minor": "(m)",
"discord-msg-page-edited": "$1 editó $2 $3 $4",
"discord-msg-page-created": "$1 creó $2 $3 $4",
"discord-msg-page-deleted": "$1 eliminó $2 $3 ($4 revisiones eliminadas)",
"discord-msg-page-undeleted-revs": "revisiones de",
"discord-msg-page-undeleted": "$1 restauró $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 cambió la visibilidad de $2 revisiones en $3",
"discord-msg-page-protect": "$1 cambió la protección de $2 $3 ($4)",
"discord-msg-page-moved": "$1 movió $2 a $3 $4 $5",
"discord-msg-user-registered": "$1 se ha registrado",
"discord-msg-user-block": "$1 bloqueó a $2 $3 ($4)",
"discord-msg-user-unblock": "$1 desbloqueó a $2",
"discord-msg-user-groups-changed": "$1 cambió los derechos de $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "nueva versión de",
"discord-msg-file-upload": "$1 subió $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 eliminó una versión del archivo $2 $3",
"discord-msg-file-undelete": "$1 restauró algunas versiones del archivo $2 $3",
"discord-msg-import": "$1 importó $2 (importado $4/$3 revisiones)",
"discord-msg-page-merge": "$1 fusionó las revisiones de $2 en $3",
"discord-msg-ext-approvedrevs-approved": "$1 aprobó una nueva revisión de $2 (revisión $3) del usuario $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 desaprobó la revisión aprobada de $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 aprobó una nueva revisión del archivo $2 ($3) del usuario $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 desaprobó la revisión aprobada del archivo $2",
"discord-msg-user-rename": "$1 renombró al usuario $2 a $3"
}
+36
View File
@@ -0,0 +1,36 @@
{
"@metadata": {
"authors": [
"Gomoko",
"Verdy p"
]
},
"discord-desc": "Envoie des messages à un canal Discord quand certains événements surviennent",
"discord-talk": "t",
"discord-contribs": "c",
"discord-diff": "diff",
"discord-minor": "(m)",
"discord-msg-page-edited": "$1 a modifié $2 $3: $4",
"discord-msg-page-created": "$1 a créé $2 $3: $4",
"discord-msg-page-deleted": "$1 a supprimé $2 ($4 version(s) supprimée(s)): $3",
"discord-msg-page-undeleted-revs": "versions pour",
"discord-msg-page-undeleted": "$1 a restauré $2 $3: $4",
"discord-msg-rev-visibility-changed": "$1 a modifié la visibilité de $2 version(s) sur $3",
"discord-msg-page-protect": "$1 a modifié la protection de $2 ($4): $3",
"discord-msg-page-moved": "$1 a renommé $2 en $3 $5: $4",
"discord-msg-user-registered": "$1 sest inscrit(e)",
"discord-msg-user-block": "$1 a bloqué $2 ($4): $3",
"discord-msg-user-unblock": "$1 a débloqué $2",
"discord-msg-user-groups-changed": "$1 a modifié les droits de $2 ($4) ($5): $3",
"discord-msg-file-upload-new": "nouvelle version de",
"discord-msg-file-upload": "$1 a téléversé $2 $3 ($5, $6x$7, $8): $4",
"discord-msg-file-delete": "$1 a supprimé une version du fichier $2: $3",
"discord-msg-file-undelete": "$1 a restauré certaines versions du fichier $2: $3",
"discord-msg-import": "$1 a importé $2 ($4/$3 révisions importées)",
"discord-msg-page-merge": "$1 a fusionné des versions de $2 vers $3",
"discord-msg-ext-approvedrevs-approved": "$1 a approuvé une nouvelle version de $2 (version $3) créée par $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 a désapprouvé la version approuvée de $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 a approuvé une nouvelle version de fichier dans $2 ($3) créée par $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 a désapprouvé la version de fichier approuvée dans $2",
"discord-msg-user-rename": "$1 a renommé lutilisateur ou lutilisatrice $2 en $3"
}
+37
View File
@@ -0,0 +1,37 @@
{
"@metadata": {
"authors": [
"Toliño"
]
},
"discord-desc": "Envía mensaxes a unha canle de Discord cando ocorren certos eventos",
"discord-talk": "conv",
"discord-contribs": "contr",
"discord-diff": "dif",
"discord-minor": "(m)",
"discord-msg-page-edited": "$1 editou «$2» $3 $4",
"discord-msg-page-created": "$1 creou «$2» $3 $4",
"discord-msg-page-deleted": "$1 eliminou «$2» $3 ($4 revisións eliminadas)",
"discord-msg-page-undeleted-revs": "revisións de",
"discord-msg-page-undeleted": "$1 restaurou $2 «$3» $4",
"discord-msg-rev-visibility-changed": "$1 cambiou a visibilidade de $2 revisións en «$3»",
"discord-msg-page-protect": "$1 cambiou a protección de «$2» $3 ($4)",
"discord-msg-page-moved": "$1 trasladou «$2» a «$3» $4 $5",
"discord-msg-user-registered": "$1 rexistrouse",
"discord-msg-user-block-timeformat": "d \\d\\e F \\d\\e Y H:i",
"discord-msg-user-block": "$1 bloqueou a $2 $3 ($4)",
"discord-msg-user-block-partial": "$1 bloqueou parcialmente a $2 $3 ($4)",
"discord-msg-user-unblock": "$1 desbloqueou a $2",
"discord-msg-user-groups-changed": "$1 cambiou os dereitos de $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "unha nova versión de",
"discord-msg-file-upload": "$1 subiu $2 «$3» $4 ($5, $6×$7, $8)",
"discord-msg-file-delete": "$1 eliminou unha versión do ficheiro «$2» $3",
"discord-msg-file-undelete": "$1 restaurou algunhas versións do ficheiro «$2» $3",
"discord-msg-import": "$1 importou «$2» (importáronse $4/$3 revisións)",
"discord-msg-page-merge": "$1 fusionou revisións de «$2» en «$3»",
"discord-msg-ext-approvedrevs-approved": "$1 aprobou unha nova revisión de «$2» (revisión $3) do usuario $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 non aprobou a revisión aprobada de «$2»",
"discord-msg-ext-approvedrevs-approved-file": "$1 aprobou unha nova revisión do ficheiro «$2» ($3) do usuario $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 non aprobou a revisión aprobada do ficheiro de «$2»",
"discord-msg-user-rename": "$1 renomeou o usuario $2 a $3"
}
+35
View File
@@ -0,0 +1,35 @@
{
"@metadata": {
"authors": [
"Amire80"
]
},
"discord-desc": "שליחת הודעות לערוץ דיסקורד כאשר אירועים מסוימים מתרחשים",
"discord-talk": "ש",
"discord-contribs": "ת",
"discord-diff": "השוואה",
"discord-minor": "(מ)",
"discord-msg-page-edited": "חשבון $1 ערך את הדף $2 $3 $4",
"discord-msg-page-created": "חשבון $1 יצר את הדף $2 $3 $4",
"discord-msg-page-deleted": "חשבון $1 מחק את הדף $2 $3 (מספר הגרסאות שנמחקו הוא $4)",
"discord-msg-page-undeleted-revs": "גרסאות של",
"discord-msg-page-undeleted": "חשבון $1 שחזר ממחיקה את הדף $2 $3 $4",
"discord-msg-rev-visibility-changed": "חשבון $1 שינה הנראות של $2 גרסאות של הדף $3",
"discord-msg-page-protect": "חשבון $1 שינה את ההגנה של הדף $2 סיבה: $3 הגדרות הגנה: ($4)",
"discord-msg-page-moved": "חשבון $1 העביר את הדף $2 לשם $3 $4 $5",
"discord-msg-user-registered": "חשבון $1 נרשם",
"discord-msg-user-block": "חשבון $1 חסם אם $2 $3 ($4)",
"discord-msg-user-unblock": "חשבון $1 שחרר מחסימה את $2",
"discord-msg-user-groups-changed": "חשבון $1 שינה את ההרשאות של $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "גרסה חדשה של",
"discord-msg-file-upload": "חשבון $1 העלה את $2 $3 $4 (גודל: $5, מידות: $6x$7, סוג: $8)",
"discord-msg-file-delete": "חשבון $1 מחק גרסה של הקובץ $2 $3",
"discord-msg-file-undelete": "חשבון $1 שחזר כמה גרסאות של קובץ $2 $3",
"discord-msg-import": "חשבון $1 ייבא את $2 (יובאו $4 מתוך $3 גרסאות)",
"discord-msg-page-merge": "חשבון $1 מיזג גרסאות מתוך $2 לתוך $3",
"discord-msg-ext-approvedrevs-approved": "חשבון $1 אישר גרסה חדשה של $2 (גרסה $3) של חשבון $4",
"discord-msg-ext-approvedrevs-unapproved": "חשבון $1 ביטל את אישור של הגרסה המאושרת של $2",
"discord-msg-ext-approvedrevs-approved-file": "חשבון $1 אישר גרסה חדשה של הקובץ $2 (גיבוב $3) של חשבון $4",
"discord-msg-ext-approvedrevs-unapproved-file": "חשבון $1 ביטל את אישור של גרסת הקובץ של $2",
"discord-msg-user-rename": "חשבון $1 שינה את השם של משתמש $2 לשם $3"
}
+37
View File
@@ -0,0 +1,37 @@
{
"@metadata": {
"authors": [
"McDutchie"
]
},
"discord-desc": "Invia messages a un canal Discord quando certe eventos occurre",
"discord-talk": "d",
"discord-contribs": "c",
"discord-diff": "diff",
"discord-minor": "(m)",
"discord-msg-page-edited": "$1 ha modificate $2 $3 $4",
"discord-msg-page-created": "$1 ha create $2 $3 $4",
"discord-msg-page-deleted": "$1 ha delite $2 $3 ($4 versiones delite)",
"discord-msg-page-undeleted-revs": "versiones pro",
"discord-msg-page-undeleted": "$1 ha restaurate $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 ha cambiate le visibilitate de of $2 versiones sur $3",
"discord-msg-page-protect": "$1 ha cambiate le protection de $2 $3 ($4)",
"discord-msg-page-moved": "$1 ha renominate $2 a $3 $4 $5",
"discord-msg-user-registered": "$1 se ha inscribite",
"discord-msg-user-block-timeformat": "j F Y H:i",
"discord-msg-user-block": "$1 ha blocate $2 $3 ($4)",
"discord-msg-user-block-partial": "$1 ha partialmente blocate $2 $3 ($4)",
"discord-msg-user-unblock": "$1 ha disblocate $2",
"discord-msg-user-groups-changed": "$1 ha cambiate le derectos de $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "nove version de",
"discord-msg-file-upload": "$1 ha incargate un $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 ha delite un version del file $2 $3",
"discord-msg-file-undelete": "$1 ha restaurate alcun versiones del file $2 $3",
"discord-msg-import": "$1 ha importate $2 ($4/$3 versiones importate)",
"discord-msg-page-merge": "$1 ha fusionate le versiones de $2 in $3",
"discord-msg-ext-approvedrevs-approved": "$1 ha approbate un nove version de $2 (version $3) del usator $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 ha disapprobate le version approbate de $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 ha approbate un nove version del file $2 ($3) del usator $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 ha disapprobate le version approbate del file $2",
"discord-msg-user-rename": "$1 ha renominate le usator $2 a $3"
}
+28
View File
@@ -0,0 +1,28 @@
{
"@metadata": {
"authors": [
"Elefentiste"
]
},
"discord-talk": "d",
"discord-contribs": "c",
"discord-diff": "dif",
"discord-minor": "(m)",
"discord-msg-page-edited": "$1 ia edita $2 $3 $4",
"discord-msg-page-created": "$1 ia crea $2 $3 $4",
"discord-msg-page-deleted": "$1 ia sutrae $2 $3 ($4 revisas ia es sutraeda)",
"discord-msg-page-undeleted": "$1 ia desutrae $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 ia cambia vidablia de $2 revisas en $3",
"discord-msg-page-protect": "$1 ia cambia proteje de $2 $3 ($4)",
"discord-msg-page-moved": "$1 ia move $2 a $3 $4 $5",
"discord-msg-user-block": "$1 ia impedi $2 $3 ($4)",
"discord-msg-user-unblock": "$1 ia desimpedi $2",
"discord-msg-file-upload": "$1 ia carga $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-import": "$1 ia emporta $2 (emportada $4/$3 revisas)",
"discord-msg-page-merge": "$1 ia fusa revisas de $2 a en $3",
"discord-msg-ext-approvedrevs-approved": "$1 ia aproba un revisa nova de $2 (revisa $3) de usor $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 ia desaproba la revisa aprobada per $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 ia aproba un revisa de fix nova de $2 ($3) de usor $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 ia desaproba la revisa de fix aprobada per $2",
"discord-msg-user-rename": "$1 ia renomi la usor $2 a $3"
}
+38
View File
@@ -0,0 +1,38 @@
{
"@metadata": {
"authors": [
"Bjankuloski06"
]
},
"discord-desc": "Испраќа пораки на канал на Дискорд кога ќе се случат извесни настани",
"discord-talk": "р",
"discord-contribs": "п",
"discord-diff": "разл",
"discord-minor": "(м)",
"discord-msg-page-edited": "$1 уреди $2 $3 $4",
"discord-msg-page-created": "$1 создаде $2 $3 $4",
"discord-msg-page-deleted": "$1 избриша $2 $3 (избришани $4 преработки)",
"discord-msg-page-undeleted-revs": "преработки за",
"discord-msg-page-undeleted": "$1 поврати $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 смени видливост на $2 преработки на $3",
"discord-msg-page-protect": "$1 смени заштита на $2 $3 ($4)",
"discord-msg-page-moved": "$1 премести $2 на $3 $4 $5",
"discord-msg-user-registered": "$1 зачленети",
"discord-msg-user-block-timeformat": "j F Y G:i ч.",
"discord-msg-user-block": "$1 блокираше $2 $3 ($4)",
"discord-msg-user-block-partial": "$1 делумно го блокираше $2 $3 ($4)",
"discord-msg-user-unblock": "$1 одблокираше $2",
"discord-msg-user-groups-changed": "$1 ги смени правата на $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "нова преработка на",
"discord-msg-file-upload": "$1 подигна $2 $3 $4 ($5, $6×$7, $8)",
"discord-msg-file-delete": "$1 избриша верзија на податотека $2 $3",
"discord-msg-file-undelete": "$1 поврати некои верзии на податотека $2 $3",
"discord-msg-import": "$1 увезе $2 (увезени $4/$3 преработки)",
"discord-timestampformat": "**G:i ч. e:**",
"discord-msg-page-merge": "$1 спои преработки од $2 во $3",
"discord-msg-ext-approvedrevs-approved": "$1 одобри нова преработка на $2 (преработка $3) од корисникот $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 тргна одобрение од одобрената преработка за $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 одобри нова преработка на податотека на $2 ($3) од корисникот $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 тргна одобрение од одобрената преработка на податотека за $2",
"discord-msg-user-rename": "$1 го преименуваше корисникот $2 во $3"
}
+38
View File
@@ -0,0 +1,38 @@
{
"@metadata": {
"authors": [
"EdoAug",
"Jon Harald Søby"
]
},
"discord-desc": "Sender meldinger til en Discord-kanal når visse hendelser forekommer",
"discord-talk": "d",
"discord-contribs": "b",
"discord-diff": "diff",
"discord-minor": "(m)",
"discord-msg-page-edited": "$1 redigerte $2 $3 $4",
"discord-msg-page-created": "$1 opprettet $2 $3 $4",
"discord-msg-page-deleted": "$1 slettet $2 $3 ($4 sideversjoner slettet)",
"discord-msg-page-undeleted-revs": "sideversjoner for",
"discord-msg-page-undeleted": "$1 gjenopprettet $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 endret synligheten til $2 sideversjoner for $3",
"discord-msg-page-protect": "$1 endra beskyttelsen av $2 $3 ($4)",
"discord-msg-page-moved": "$1 flyttet $2 til $3 $4 $5",
"discord-msg-user-registered": "$1 registrerte",
"discord-msg-user-block-timeformat": "j. F Y \"kl.\" H:i",
"discord-msg-user-block": "$1 blokkerte $2 $3 ($4)",
"discord-msg-user-block-partial": "$1 blokkerte $2 delvis $3 ($4)",
"discord-msg-user-unblock": "$1 opphevde blokkeringen til $2",
"discord-msg-user-groups-changed": "$1 endret rettighetene til $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "ny versjon av",
"discord-msg-file-upload": "$1 lastet opp $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 slettet en versjon av fila $2 $3",
"discord-msg-file-undelete": "$1 gjenopprettet noen versjoner av fila $2 $3",
"discord-msg-import": "$1 importerte $2 (importerte $4/$3 sideversjoner)",
"discord-msg-page-merge": "$1 flettet sideversjoner fra $2 inn i $3",
"discord-msg-ext-approvedrevs-approved": "$1 godkjente en ny sideversjon av $2 (sideversjon $3) fra brukeren $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 trakk tilbake godkjenningen av sideversjonen for $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 godkjente en ny versjon av fila $2 ($3) fra brukeren $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 trakk tilbake godkjenningen av filversjon for $2",
"discord-msg-user-rename": "$1 omdøpte brukeren $2 til $3"
}
+39
View File
@@ -0,0 +1,39 @@
{
"@metadata": {
"authors": [
"McDutchie",
"SPQRobin",
"Vistaus"
]
},
"discord-desc": "Stuurt berichten naar een Discord-kanaal wanneer bepaalde gebeurtenissen plaatsvinden",
"discord-talk": "o",
"discord-contribs": "b",
"discord-diff": "wijz",
"discord-minor": "(k)",
"discord-msg-page-edited": "$1 heeft $2 bewerkt $3 $4",
"discord-msg-page-created": "$1 heeft $2 aangemaakt $3 $4",
"discord-msg-page-deleted": "$1 heeft $2 verwijderd $3 ($4 versies verwijderd)",
"discord-msg-page-undeleted-revs": "versies voor",
"discord-msg-page-undeleted": "$1 heeft $2 teruggezet $3 $4",
"discord-msg-rev-visibility-changed": "$1 heeft de zichtbaarheid van $2 versies op $3 veranderd",
"discord-msg-page-protect": "$1 heeft de beveiliging van $2 veranderd $3 ($4)",
"discord-msg-page-moved": "$1 heeft $2 hernoemd tot $3 $4 $5",
"discord-msg-user-registered": "$1 heeft zich ingeschreven",
"discord-msg-user-block-timeformat": "j F Y H:i",
"discord-msg-user-block": "$1 heeft $2 geblokkeerd $3 ($4)",
"discord-msg-user-block-partial": "$1 heeft $2 gedeeltelijk geblokkeerd $3 ($4)",
"discord-msg-user-unblock": "$1 heeft $2 gedeblokkeerd",
"discord-msg-user-groups-changed": "$1 heeft de rechten van $2 veranderd $3 ($4) ($5)",
"discord-msg-file-upload-new": "nieuwe versie van",
"discord-msg-file-upload": "$1 heeft een $2 $3 geüpload $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 heeft een versie van het bestand $2 verwijderd $3",
"discord-msg-file-undelete": "$1 heeft bepaalde versies van het bestand $2 teruggezet $3",
"discord-msg-import": "$1 heeft $2 geïmporteerd (er zijn $4 van de $3 versies geïmporteerd)",
"discord-msg-page-merge": "$1 heeft de versies van $2 samengevoegd met $3",
"discord-msg-ext-approvedrevs-approved": "$1 heeft een nieuwe versie van $2 goedgekeurd (versie $3, auteur $4)",
"discord-msg-ext-approvedrevs-unapproved": "$1 heeft de goedkeuring van de goedgekeurde versie van $2 ingetrokken",
"discord-msg-ext-approvedrevs-approved-file": "$1 heeft een nieuwe bestandsversie van $2 ($3) goedgekeurd, auteur: $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 heeft de goedkeuring van de goedgekeurde bestandsversie van $2 ingetrokken",
"discord-msg-user-rename": "$1 heeft de gebruiker $2 hernoemd tot $3"
}
+26
View File
@@ -0,0 +1,26 @@
{
"@metadata": {
"authors": [
"Railfail536"
]
},
"discord-desc": "Wysyła wiadomości o dokonywanych akcjach na serwer Discord",
"discord-talk": "d",
"discord-contribs": "w",
"discord-diff": "różn.",
"discord-msg-page-edited": "$1 edytował $2 $3 $4",
"discord-msg-page-deleted": "$1 usunął $2 $3 ($4 wersje usunięte)",
"discord-msg-page-undeleted-revs": "wersje",
"discord-msg-page-undeleted": "$1 odtworzył $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 zmienił widoczność $2 wersji $3",
"discord-msg-page-protect": "$1 zmienił poziom zabezpoeczenia strony $2 $2 $3 ($4)",
"discord-msg-page-moved": "$1 przeniósł $2 na $3 $4 $5",
"discord-msg-user-registered": "$1 założył konto",
"discord-msg-user-block": "$1 zablokował $2 $3 ($4)",
"discord-msg-user-unblock": "$1 zdjął blokadę z $2",
"discord-msg-user-groups-changed": "$1 zmienił uprawnienia użytkownika $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "nową wersję",
"discord-msg-file-upload": "$1 przesłał $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 usunął wersję pliku $2 $3",
"discord-msg-file-undelete": "$1 odtworzył wersje pliku $2 $3"
}
+43 -24
View File
@@ -1,26 +1,45 @@
{
"discord-desc": "The description used for the Discord extension",
"discord-userlinks": "Used for display of the user links. Parameters\n* $1 - User page link\n* $2 - discord-talk\n* $3 - discord-contribs",
"discord-revisionlinks": "Used for display of revision links. Parameters\n* $1 - discord-diff\n* $2 - discord-minor\n* $3 - discord-size",
"discord-talk": "Used as the text for $2 in discord-userlinks",
"discord-contribs": "Used as the text for $3 in discord-userlinks",
"discord-diff": "Used as the text for $1 in discord-revisionlinks",
"discord-minor": "Used as the text for $2 in discord-revisionlinks",
"discord-size": "Used as the text for $3 in discord-revisionlinks. Parameters\n* $1 - Calculated revision size diff",
"discord-edit": "Message sent to Discord for when a page edit/creation is made. Parameters:\n* $1 - discord-userlinks\n* $2 - Page link\n* $3 - discord-revisionlinks\n* $4 - Summary (always surrounded in tildes)",
"discord-articledelete": "Message sent to Discord when a page is deleted. Parameters:\n* $1 - discord-userlinks\n* $2 - Page link\n* $3 - Reason (always surrounded in tildes)\n* $4 - Number of revisions deleted",
"discord-undeleterev": "Used as the text for $2 in discord-articleundelete if revisions are being undeleted rather than a page",
"discord-articleundelete": "Message sent to Discord when pages/revisions are undeleted. Parameters:\n* $1 - discord-userlinks\n* $2 - discord-undeleterev\n* $3 - Page link\n* $4 - Comment (always surrounded in tildes)",
"discord-revvisibility": "Message sent to Discord when the visibility of revisions is changed. Parameters:\n$1 - discord-userlinks\n* $2 - Number of revisions\n* $3 - Page link",
"discord-articleprotect": "Message sent to Discord when an article's protection is changed. Parameters:\n$1 - discord-userlinks\n* $2 - Page link\n* $3 - Reason (always surrounded in tildes)\n* $4 - Protection settings",
"discord-titlemove": "Message sent to Discord when an article is moved. Parameters:\n$1 - discord-userlinks\n$2 - Old page link\n$3 - New page link\n$4 - Reason (always surrounded in tildes)\n$5 - discord-revisionlinks",
"discord-localusercreated": "Message sent to Discord when a user registers. Parameters:\n$1 - discord-userlinks",
"discord-blocktimeformat": "The formatting used in the date() function for displaying the time a user is blocked for.",
"discord-blockipcomplete": "Message sent to Discord when a user is blocked. Parameters:\n$1 - discord-userlinks (performer)\n$2 - discord-userlinks (target)\n$3 - Reason (always surrounded in tildes)\n$4 - Expiry text (using discord-blocktimeformat)",
"discord-unblockusercomplete": "Message sent to Discord when a user is unblocked. Parameters:\n$1 - discord-userlinks (performer)\n$2 - discord-userlinks (target)",
"discord-usergroupschanged": "Message sent to Discord when a user's group is changed. Parameters:\n$1 - discord-userlinks (performer)\n$2 -discord-userlinks (target)\n$3 - Reason (always surrounded in tildes)\n$4 - Added rights (prepended by +)\n$5 - Removed rights (prepended by -)",
"discord-uploadnewver": "Used as the text for $2 in discord-uploadcomplete",
"discord-uploadcomplete": "Message sent to Discord when an upload is made. Parameters:\n$1 - discord-userlinks\n$2 - discord-uploadnewver\n$3 - File link\n$4 - Comment (always surrounded in tildes)\n$5 - Size (formatted as KB/MB/GB)\n$6 - File width\n$7 - File height\n$8 - File MIME type",
"discord-filedeletecomplete": "Message sent to Discord when a file version is deleted (not an entire file). Parameters:\n$1 - discord-userlinks\n$2 - File link\n$3 - Comment (always surrounded in tildes)",
"discord-fileundeletecomplete": "Message sent to Discord when a file version is restored (not an entire file). Parameters:\n$1 - discord-userlinks\n$2 - File link\n$3 - Comment (always surrounded in tildes)"
"@metadata": {
"authors": [
"Abijeet Patro",
"Amire80",
"Jayden",
"Jayden Bailey",
"McDutchie"
]
},
"discord-desc": "The description used for the Discord extension",
"discord-userlinks": "{{optional}}\nUsed for display of the user links. Parameters\n* $1 - User page link\n* $2 - {{msg-mw|discord-talk}}\n* $3 - {{msg-mw|discord-contribs}}",
"discord-revisionlinks": "{{Optional}}\nUsed for display of revision links. Parameters\n* $1 - {{msg-mw|discord-diff}}\n* $2 - {{msg-mw|discord-minor}}\n* $3 - {{msg-mw|discord-size}}",
"discord-talk": "Short for \"talk\".\n\nUsed as the text for $2 in {{msg-mw|discord-userlinks}}",
"discord-contribs": "Short for \"contributions\".\n\nUsed as the text for $3 in {{msg-mw|discord-userlinks}}",
"discord-diff": "Used as the text for $1 in discord-revisionlinks",
"discord-minor": "Short for \"minor edit\". The letter should be the same as in {{msg-mw|Minoreditletter}}.\n\nUsed as the text for $2 in {{msg-mw|discord-revisionlinks}}.",
"discord-size": "{{Optional}}\nUsed as the text for $3 in discord-revisionlinks. Parameters\n* $1 - Calculated revision size diff",
"discord-msg-page-edited": "Message sent to Discord for when a page edit is made. Parameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - Page link\n* $3 - {{msg-mw|discord-revisionlinks}}\n* $4 - Summary (always surrounded in tildes)",
"discord-msg-page-created": "Message sent to Discord for when a page creation is made. Parameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - Page link\n* $3 - {{msg-mw|discord-revisionlinks}}\n* $4 - Summary (always surrounded in tildes)",
"discord-msg-page-deleted": "Message sent to Discord when a page is deleted. Parameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - Page link\n* $3 - Reason (always surrounded in tildes)\n* $4 - Number of revisions deleted",
"discord-msg-page-undeleted-revs": "Used as the text for $2 in discord-articleundelete if revisions are being undeleted rather than a page",
"discord-msg-page-undeleted": "Message sent to Discord when pages/revisions are undeleted.\nParameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - {{msg-mw|discord-msg-undeleted-revs}}\n* $3 - Page link\n* $4 - Comment (always surrounded in tildes)",
"discord-msg-rev-visibility-changed": "Message sent to Discord when the visibility of revisions is changed.\nParameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - Number of revisions\n* $3 - Page link",
"discord-msg-page-protect": "Message sent to Discord when an article's protection is changed.\nParameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - Page link\n* $3 - Reason (always surrounded in tildes)\n* $4 - Protection settings",
"discord-msg-page-moved": "Message sent to Discord when an article is moved. Parameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - Old page link\n* $3 - New page link\n* $4 - Reason (always surrounded in tildes)\n* $5 - {{msg-mw|discord-revisionlinks}}",
"discord-msg-user-registered": "Message sent to Discord when a user registers.\nParameters:\n* $1 - {{msg-mw|discord-userlinks}}",
"discord-msg-user-block-timeformat": "{{optional}}\n\nThe formatting used in the date() function for displaying the time a user is blocked for.\n\nSee also: https://www.php.net/manual/en/datetime.format.php",
"discord-msg-user-block": "Message sent to Discord when a user is blocked. Parameters:\n* $1 - {{msg-mw|discord-userlinks}} (performer)\n* $2 - {{msg-mw|discord-userlinks}} (target)\n* $3 - Reason (always surrounded in tildes)\n* $4 - Expiry text (using {{msg-mw|discord-msg-user-block-timeformat}})",
"discord-msg-user-block-partial": "Message sent to Discord when a user is blocked partially. Parameters:\n* $1 - {{msg-mw|discord-userlinks}} (performer)\n* $2 - {{msg-mw|discord-userlinks}} (target)\n* $3 - Reason (always surrounded in tildes)\n* $4 - Expiry text (using {{msg-mw|discord-msg-user-block-timeformat}})",
"discord-msg-user-unblock": "Message sent to Discord when a user is unblocked. Parameters:\n* $1 - {{msg-mw|discord-userlinks}} (performer)\n* $2 - {{msg-mw|discord-userlinks}} (target)",
"discord-msg-user-groups-changed": "Message sent to Discord when a user's group is changed. Parameters:\n* $1 - {{msg-mw|discord-userlinks}} (performer)\n* $2 - {{msg-mw|discord-userlinks}} (target)\n* $3 - Reason (always surrounded in tildes)\n* $4 - Added rights (prepended by +)\n* $5 - Removed rights (prepended by -)",
"discord-msg-file-upload-new": "Used as the text for $2 in {{msg-mw|discord-msg-file-upload}}",
"discord-msg-file-upload": "Message sent to Discord when an upload is made. Parameters:\n\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - {{msg-mw|discord-msg-file-upload-new}}\n* $3 - File link\n* $4 - Comment (always surrounded in tildes)\n* $5 - Size (formatted as KB/MB/GB)\n* $6 - File width\n* $7 - File height\n* $8 - File MIME type",
"discord-msg-file-delete": "Message sent to Discord when a file version is deleted (not an entire file).\nParameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - File link\n* $3 - Comment (always surrounded in tildes)",
"discord-msg-file-undelete": "Message sent to Discord when a file version is restored (not an entire file).\nParameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - File link\n* $3 - Comment (always surrounded in tildes)",
"discord-msg-import": "Message sent to Discord when a page is imported. Parameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - Page link\n* $3 - Number of revisions in XML file\n* $4 - Number of revisions successfully imported",
"discord-timestampformat": "{{optional}}\n\nThe formatting used in the gmdate() function for displaying the time an event happened in UTC.\n\nSee also: https://www.php.net/manual/en/datetime.format.php",
"discord-msg-page-merge": "Message sent to Discord when page histories are merged. Parameters:\n* $1 - {{msg-mw|discord-userlinks}}\n* $2 - Target link\n* $3 - Destination link",
"discord-msg-ext-approvedrevs-approved": "Message sent to Discord when a revision is approved (Approved Revs extension).\nParameters:\n* $1 - {{msg-mw|discord-userlinks}} (admin user)\n* $2 - Target link\n* $3 - Revision link or ID\n* $4 - {{msg-mw|discord-userlinks}} (revision author) or ID",
"discord-msg-ext-approvedrevs-unapproved": "Message sent to Discord when a revision is unapproved (Approved Revs extension).\nParameters:\n* $1 - {{msg-mw|discord-userlinks}} (admin user)\n* $2 - Target link",
"discord-msg-ext-approvedrevs-approved-file": "Message sent to Discord when a file revision is approved (Approved Revs extension).\nParameters:\n* $1 - {{msg-mw|discord-userlinks}} (admin user)\n* $2 - Target link\n* $3 - SHA of uploaded file\n* $4 - {{msg-mw|discord-userlinks}} (revision author)",
"discord-msg-ext-approvedrevs-unapproved-file": "Message sent to Discord when a file revision is unapproved (Approved Revs extension).\nParameters:\n* $1 - {{msg-mw|discord-userlinks}} (admin user)\n* $2 - Target link",
"discord-msg-user-rename": "Message sent to Discord when a user is renamed.\nParameters:\n* $1 - {{msg-mw|discord-userlinks}} (admin user)\n* $2 - Old username\n* $3 - New username link"
}
+42
View File
@@ -0,0 +1,42 @@
{
"@metadata": {
"authors": [
"Engineer56",
"Kareyac",
"Yurina Tatiana"
]
},
"discord-desc": "Отправляет сообщения на канал в Discord при возникновении некоторых событий.",
"discord-userlinks": "$1 ($2|$3)",
"discord-revisionlinks": "($1) $2 $3",
"discord-talk": "о",
"discord-contribs": "c",
"discord-diff": "разн.",
"discord-minor": "(m)",
"discord-size": "($1)",
"discord-msg-page-edited": "$1 отредактировал $2 $3 $4",
"discord-msg-page-created": "$1 создал $2 $3 $4",
"discord-msg-page-deleted": "$1 удалил $2 $3 ($4 версии удалены)",
"discord-msg-page-undeleted-revs": "версии",
"discord-msg-page-undeleted": "$1 восстановил $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 изменил видимость $2 версий на $3",
"discord-msg-page-protect": "$1 изменил защиту $2 $3 ($4)",
"discord-msg-page-moved": "$1 переместил $2 на $3 $4 $5",
"discord-msg-user-registered": "$1 зарегистрировался",
"discord-msg-user-block-timeformat": "d F Y H:i",
"discord-msg-user-block": "$1 заблокировал $2 $3 ($4)",
"discord-msg-user-unblock": "$1 разблокировал $2",
"discord-msg-user-groups-changed": "$1 изменил права $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "новая версия",
"discord-msg-file-upload": "$1 загрузил $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 удалил версию файла $2 $3",
"discord-msg-file-undelete": "$1 восстановил некоторые версии файла $2 $3",
"discord-msg-import": "$1 импортировал $2 (импортировано $4/$3 версий)",
"discord-timestampformat": "**H:i e:**",
"discord-msg-page-merge": "$1 объединил версии из $2 в $3",
"discord-msg-ext-approvedrevs-approved": "$1 одобрил новую версию $2 (версия $3) от пользователя $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 не одобрил утверждённую версию $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 одобрил новую версию файла $2 ($3) от пользователя $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 не одобрил утверждённую версию файла $2",
"discord-msg-user-rename": "$1 переименовал пользователя $2 в $3"
}
+37
View File
@@ -0,0 +1,37 @@
{
"@metadata": {
"authors": [
"Eleassar",
"Upwinxp"
]
},
"discord-desc": "Pošlje sporočila na kanal Discord ob nekaterih dogodkih",
"discord-talk": "t",
"discord-contribs": "c",
"discord-diff": "razl",
"discord-minor": "(m)",
"discord-msg-page-edited": "$1 je uredil_a $2 $3 $4",
"discord-msg-page-created": "$1 je ustvaril_a $2 $3 $4",
"discord-msg-page-deleted": "$1 je izbrisal_a $2 $3 (izbrisanih $4 redakcij)",
"discord-msg-page-undeleted-revs": "redakcije za",
"discord-msg-page-undeleted": "$1 je odizbrisal_a $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 je spremenil_a vidnost $2 redakcij strani $3",
"discord-msg-page-protect": "$1 je spremenil_a zaščito $2 $3 ($4)",
"discord-msg-page-moved": "$1 je prestavil_a $2 na $3 $4 $5",
"discord-msg-user-registered": "Registracija $1",
"discord-msg-user-block-timeformat": "d. F Y, H:i",
"discord-msg-user-block": "$1 je blokiral_a $2 $3 ($4)",
"discord-msg-user-unblock": "$1 je odblokiral_a $2",
"discord-msg-user-groups-changed": "$1 je spremenil_a pravice $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "nova različica datoteke",
"discord-msg-file-upload": "$1 je naložil_a $2 $3 $4 ($5, $6&nbsp;×&nbsp;$7, $8)",
"discord-msg-file-delete": "$1 je izbrisal_a različico datoteke $2 $3",
"discord-msg-file-undelete": "$1 je obnovil_a nekaj različic datoteke $2 $3",
"discord-msg-import": "$1 je uvozil_a $2 (uvoženih $4/$3 redakcij)",
"discord-msg-page-merge": "$1 je združil_a redakcije iz $2 v $3",
"discord-msg-ext-approvedrevs-approved": "$1 je odobril_a novo redakcijo $2 (redakcija $3) uporabnika_ce $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 je od-odobrila odobreno redakcijo za $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 je odobril_a novo različico datoteke $2 ($3) uporabnika_ce $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 je od-odobrila odobreno redakcijo datoteke za $2",
"discord-msg-user-rename": "$1 je preimenoval_a uporabnika $2 v $3"
}
+36
View File
@@ -0,0 +1,36 @@
{
"@metadata": {
"authors": [
"KockaAdmiralac",
"Milicevic01"
]
},
"discord-desc": "Шаље поруке на Discord канал када се десе одређени догађаји",
"discord-talk": "р",
"discord-contribs": "д",
"discord-diff": "разл",
"discord-minor": "(м)",
"discord-msg-page-edited": "$1 је уредио/ла $2 $3 $4",
"discord-msg-page-created": "$1 је направио/ла $2 $3 $4",
"discord-msg-page-deleted": "$1 је обрисао/ла $2 $3 ($4 измена обрисано)",
"discord-msg-page-undeleted-revs": "измене за",
"discord-msg-page-undeleted": "$1 је вратио/ла $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 је променио/ла видљивост измене $2 на $3",
"discord-msg-page-protect": "$1 је променио/ла подешавања заштите $2 $3 ($4)",
"discord-msg-page-moved": "$1 је преместио/ла $2 на $3 $4 $5",
"discord-msg-user-registered": "$1 се регистровао/ла",
"discord-msg-user-block": "$1 је блокирао/ла $2 $3 ($4)",
"discord-msg-user-unblock": "$1 је деблокирао/ла $2",
"discord-msg-user-groups-changed": "$1 је променио/ла права $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "нову верзију",
"discord-msg-file-upload": "$1 је отпремио/ла $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 је обрисао/ла верзију датотеке $2 $3",
"discord-msg-file-undelete": "$1 је вратио/ла поједине верзије датотеке $2 $3",
"discord-msg-import": "$1 је увезао/ла $2 (увезено $4/$3 измена)",
"discord-msg-page-merge": "$1 је спојио/ла измене из $2 у $3",
"discord-msg-ext-approvedrevs-approved": "$1 је одобрио/ла нову измену $2 (измена $3) корисника $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 је поништио/ла одобрену измену за $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 је одобрио/ла нову верзију датотеке $2 ($3) корисника $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 је поништио/ла одобрену верзију датотеке $2",
"discord-msg-user-rename": "$1 је преименовао/ла корисника $2 у $3"
}
+35
View File
@@ -0,0 +1,35 @@
{
"@metadata": {
"authors": [
"KockaAdmiralac"
]
},
"discord-desc": "Šalje poruke na Discord kanal kada se dese određeni događaji",
"discord-talk": "r",
"discord-contribs": "d",
"discord-diff": "razl",
"discord-minor": "(m)",
"discord-msg-page-edited": "$1 je uredio/-la $2 $3 $4",
"discord-msg-page-created": "$1 je napravio/-la $2 $3 $4",
"discord-msg-page-deleted": "$1 je obrisao/-la $2 $3 ($4 izmena obrisano)",
"discord-msg-page-undeleted-revs": "izmene za",
"discord-msg-page-undeleted": "$1 je vratio/-la $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 je promenio/-la vidljivost $2 izmena na $3",
"discord-msg-page-protect": "$1 je promenio/-la podešavanja zaštite na $2 $3 ($4)",
"discord-msg-page-moved": "$1 je pomerio/-la $2 na $3 $4 $5",
"discord-msg-user-registered": "$1 se registrovao/-la",
"discord-msg-user-block": "$1 je blokirao/-la $2 $3 ($4)",
"discord-msg-user-unblock": "$1 je deblokirao/-la $2",
"discord-msg-user-groups-changed": "$1 je promenio/-la prava od $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "novu verziju",
"discord-msg-file-upload": "$1 je otpremio/-la $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 je obrisao/-la verziju datoteke $2 $3",
"discord-msg-file-undelete": "$1 je vratio/-la pojedine verzije datoteke $2 $3",
"discord-msg-import": "$1 je uvezao/-la $2 (uvezeno $4/$3 izmena)",
"discord-msg-page-merge": "$1 je spojio/-la izmene iz $2 u $3",
"discord-msg-ext-approvedrevs-approved": "$1 je odobrio/-la novu izmenu $2 (izmena $3) od korisnika $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 je poništio/-la odobrenje izmene $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 je odobrio/-la novu izmenu datoteke $2 ($3) od korisnika $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 je poništio/-la odobrenje izmene datoteke $2",
"discord-msg-user-rename": "$1 je preimenovao/-la korisnika $2 u $3"
}
+36
View File
@@ -0,0 +1,36 @@
{
"@metadata": {
"authors": [
"Sabelöga",
"Stefan2255"
]
},
"discord-desc": "Skickar meddelanden till en Discord-kanal när vissa händelser sker",
"discord-talk": "t",
"discord-contribs": "c",
"discord-diff": "skillnad",
"discord-minor": "(m)",
"discord-msg-page-edited": "$1 redigerade $2 $3 $4",
"discord-msg-page-created": "$1 skapade $2 $3 $4",
"discord-msg-page-deleted": "$1 raderade $2 $3 ( $4 sidvisioner raderade)",
"discord-msg-page-undeleted-revs": "sidversioner för",
"discord-msg-page-undeleted": "$1 återställde $2 $3 $4",
"discord-msg-rev-visibility-changed": "$1 ändrade synligheten för $2 sidversioner på $3",
"discord-msg-page-protect": "$1 ändrade skrivskydd av $2 $3 ($4)",
"discord-msg-page-moved": "$1 flyttade $2 till $3 $4 $5",
"discord-msg-user-registered": "$1 registrerade",
"discord-msg-user-block": "$1 blockerade $2 $3 ($4)",
"discord-msg-user-unblock": "$1 avblockerade $2",
"discord-msg-user-groups-changed": "$1 ändrade rättigheter för $2 $3 ($4) ($5)",
"discord-msg-file-upload-new": "ny version av",
"discord-msg-file-upload": "$1 laddade upp $2 $3 $4 ($5, $6x$7, $8)",
"discord-msg-file-delete": "$1 raderad en version av filen $2 $3",
"discord-msg-file-undelete": "$1 återställde några versioner av filen $2 $3",
"discord-msg-import": "$1 importerade $2 (importerade $4/$3 sidversioner)",
"discord-msg-page-merge": "$1 sammanfogade sidversioner från $2 till $3",
"discord-msg-ext-approvedrevs-approved": "$1 godkände en ny sidversion av $2 (sidversion $3) från användare $4",
"discord-msg-ext-approvedrevs-unapproved": "$1 drog in godkännandet av sidversionen för $2",
"discord-msg-ext-approvedrevs-approved-file": "$1 godkände en ny filrevision av $2 ($3) från användare $4",
"discord-msg-ext-approvedrevs-unapproved-file": "$1 drog in godkännandet för filrevisionen för $2",
"discord-msg-user-rename": "$1 bytte namn på användare $2 till $3"
}
+21
View File
@@ -0,0 +1,21 @@
{
"@metadata": {
"authors": [
"Tbodt"
]
},
"discord-talk": "tk",
"discord-contribs": "pl",
"discord-diff": "ante",
"discord-minor": "(lili)",
"discord-msg-page-edited": "$1 li ante e lipu $2 $3 $4",
"discord-msg-page-created": "$1 li pali e lipu $2 $3 $4",
"discord-msg-page-deleted": "$1 li weka e lipu $2 $3 (lipu li ante lon tenpo $4)",
"discord-msg-page-undeleted": "$1 li lon sin e lipu $2 $3 $4",
"discord-msg-page-moved": "$1 li ante e nimi lipu $2 tawa nimi $3 $4 $5",
"discord-msg-user-registered": "$1 li kama lon",
"discord-msg-user-block": "$1 li ken ala e $2 $3 ($4)",
"discord-msg-user-unblock": "$1 li ken sin e $2",
"discord-msg-user-groups-changed": "$1 li ante e ken jan lon $2 $3 ($4) ($5)",
"discord-msg-user-rename": "$1 li ante e nimi jan $2 tawa nimi $3"
}
+37
View File
@@ -0,0 +1,37 @@
{
"@metadata": {
"authors": [
"Asma",
"Hedda",
"Joseph"
]
},
"discord-desc": "Belirli olaylar gerçekleştiğinde bir Discord kanalına mesaj gönderir",
"discord-talk": "m",
"discord-contribs": "k",
"discord-diff": "fark",
"discord-minor": "(k)",
"discord-msg-page-edited": "$1, $2 $3 $4 sayfasını düzenledi",
"discord-msg-page-created": "$1, $2 $3 $4 sayfasını oluşturdu",
"discord-msg-page-deleted": "$1, $3 sebebiyle $2 sayfasını sildi ($4 değişiklik silindi)",
"discord-msg-page-undeleted-revs": "şunun için değişiklikler:",
"discord-msg-page-undeleted": "$1, $2 $3 $4 sayfasını silemedi",
"discord-msg-rev-visibility-changed": "$1, $3 sayfasındaki $2 değişikliğin görünürlüğünü değiştirdi",
"discord-msg-page-protect": "$1, $2 sayfasının korunmasını $3 ($4) sebebiyle değiştirdi",
"discord-msg-page-moved": "$1, $2 sayfasını $4 $5 sebebiyle $3 olacak şekildi taşıdı",
"discord-msg-user-registered": "$1 kayıt oldu",
"discord-msg-user-block": "$1, $3 ($4) sebebiyle $2 kullanıcısını engelledi",
"discord-msg-user-unblock": "$1, $2 kullanıcısının engelini kaldırdı",
"discord-msg-user-groups-changed": "$1, $3 ($4) ($5) sebebiyle $2 kullanıcısının haklarını değiştirdi",
"discord-msg-file-upload-new": "şunun yeni sürümü:",
"discord-msg-file-upload": "$1, $2 $3 $4 ($5, $6x$7, $8) yükledi",
"discord-msg-file-delete": "$1, $2 $3 dosyasının bir sürümünü sildi",
"discord-msg-file-undelete": "$1, $2 $3 dosyasının bazı sürümlerini geri yükledi",
"discord-msg-import": "$1, $2 ice aktardı ($4 içe aktarılan/$3 revizyon)",
"discord-msg-page-merge": "$1, $2 ile $3 için revizyonları birleştirdi",
"discord-msg-ext-approvedrevs-approved": "$1, $4 kullanıcısından $2 (değişiklik $3) için yapılan yeni bir değişikliği onayladı",
"discord-msg-ext-approvedrevs-unapproved": "$1, $2 için yapılan onaylı değişikliği reddetti",
"discord-msg-ext-approvedrevs-approved-file": "$1, $4 kullanıcısı tarafından $2 ($3) için yapılan yeni bir dosya değişikliğini onayladı",
"discord-msg-ext-approvedrevs-unapproved-file": "$1, $2 için onaylanan değişikliği reddetti",
"discord-msg-user-rename": "$1, $2 kullanıcısını $3 olarak yeniden adlandırdı"
}
+39
View File
@@ -0,0 +1,39 @@
{
"@metadata": {
"authors": [
"Anterdc99",
"Peterxy12"
]
},
"discord-desc": "当某些事件发生时向Discord频道发送消息",
"discord-userlinks": "$1$2|$3",
"discord-talk": "讨论",
"discord-contribs": "贡献",
"discord-diff": "差异",
"discord-minor": "(小)",
"discord-msg-page-edited": "$1编辑了$2、$3$4",
"discord-msg-page-created": "$1创建了$2、$3$4",
"discord-msg-page-deleted": "$1删除了$2$3(已删除版本$4",
"discord-msg-page-undeleted-revs": "版本为",
"discord-msg-page-undeleted": "$1还原了$2 $3,原因:$4",
"discord-msg-rev-visibility-changed": "$1更改了在$3上版本$2的可见性",
"discord-msg-page-protect": "$1更改了$2的保护($4),原因:$3",
"discord-msg-page-moved": "$1将$2移动到$3,原因:$4,版本链接:$5",
"discord-msg-user-registered": "$1已注册",
"discord-msg-user-block-timeformat": "d F Y H:i",
"discord-msg-user-block": "$1封禁了$2,原因:$3$4",
"discord-msg-user-block-partial": "$1已部分封禁$2,原因:$3(到期:$4)",
"discord-msg-user-unblock": "$1解封了$2",
"discord-msg-user-groups-changed": "$1更改了$2的权限(新增:$4)(移除:$5),原因:$3",
"discord-msg-file-upload-new": "新版本的",
"discord-msg-file-upload": "$1上传了$2 $3$5$6x$7$8),原因:$4",
"discord-msg-file-delete": "$1删除了文件$2的一个版本,原因:$3",
"discord-msg-file-undelete": "$1恢复了文件$2的一些版本,原因:$3",
"discord-msg-import": "$1导入了$2(导入了$4/$3个版本)",
"discord-msg-page-merge": "$1将$2的版本合并到$3",
"discord-msg-ext-approvedrevs-approved": "$1批准了来自用户$4的$2新版本$3",
"discord-msg-ext-approvedrevs-unapproved": "$1取消批准$2的已批准版本",
"discord-msg-ext-approvedrevs-approved-file": "$1批准了来自用户$4的$2的新文件版本($3)",
"discord-msg-ext-approvedrevs-unapproved-file": "$1取消批准$2已批准的文件版本",
"discord-msg-user-rename": "$1将用户$2重命名为$3"
}
+37
View File
@@ -0,0 +1,37 @@
{
"@metadata": {
"authors": [
"Kly"
]
},
"discord-desc": "當某些事件發生時向 Discord 頻道發送訊息",
"discord-talk": "討論",
"discord-contribs": "貢獻",
"discord-diff": "差異",
"discord-minor": "m",
"discord-msg-page-edited": "$1編輯了$2、$3$4",
"discord-msg-page-created": "$1建立了$2、$3$4",
"discord-msg-page-deleted": "$1刪除了$2$3(已刪除修訂 $4",
"discord-msg-page-undeleted-revs": "修訂為",
"discord-msg-page-undeleted": "$1取消刪除$2 $3,意見:$4",
"discord-msg-rev-visibility-changed": "$1更改了在$3上修訂$2的可見度",
"discord-msg-page-protect": "$1更改了$2的保護($4),原因:$3",
"discord-msg-page-moved": "$1將$2移動到$3,原因:$4,修訂連結:$5",
"discord-msg-user-registered": "$1已註冊",
"discord-msg-user-block-timeformat": "d F Y H:i",
"discord-msg-user-block": "$1封鎖了$2,原因:$3$4",
"discord-msg-user-block-partial": "$1已部分封鎖$2,原因:$3(到期:$4)",
"discord-msg-user-unblock": "$1取消封鎖$2",
"discord-msg-user-groups-changed": "$1更改了$2的權限(新增:$4)(移除:$5),原因:$3",
"discord-msg-file-upload-new": "新版本的",
"discord-msg-file-upload": "$1上傳了$2 $3$5$6x$7$8),意見:$4",
"discord-msg-file-delete": "$1刪除了檔案$2的一個版本,意見:$3",
"discord-msg-file-undelete": "$1恢復了檔案$2的一些版本,意見:$3",
"discord-msg-import": "$1匯入了$2(匯入 $4/$3 個修訂)",
"discord-msg-page-merge": "$1將$2的修訂合併到$3",
"discord-msg-ext-approvedrevs-approved": "$1批准了來自使用者$4的$2新修訂($3)",
"discord-msg-ext-approvedrevs-unapproved": "$1取消批准$2的已批准修訂",
"discord-msg-ext-approvedrevs-approved-file": "$1批准了來自使用者$4的$2新檔案修訂($3)",
"discord-msg-ext-approvedrevs-unapproved-file": "$1取消批准$2已批准的檔案修訂",
"discord-msg-user-rename": "$1將使用者$2重新命名為$3"
}
-7
View File
@@ -1,7 +0,0 @@
<phpunit colors="true">
<testsuites>
<testsuite name="Utils tests">
<file>tests/UtilsTests.php</file>
</testsuite>
</testsuites>
</phpunit>
+666 -244
View File
@@ -1,294 +1,716 @@
<?php
namespace MediaWiki\Extension\Discord;
use ForeignTitle;
use ImagePage;
use LocalFile;
use ManualLogEntry;
use MediaWiki\Auth\Hook\LocalUserCreatedHook;
use MediaWiki\Block\DatabaseBlock;
use MediaWiki\Context\RequestContext;
use MediaWiki\Hook\AfterImportPageHook;
use MediaWiki\Hook\ArticleMergeCompleteHook;
use MediaWiki\Hook\ArticleRevisionVisibilitySetHook;
use MediaWiki\Hook\BlockIpCompleteHook;
use MediaWiki\Hook\FileDeleteCompleteHook;
use MediaWiki\Hook\FileUndeleteCompleteHook;
use MediaWiki\Hook\PageMoveCompleteHook;
use MediaWiki\Hook\UnblockUserCompleteHook;
use MediaWiki\Hook\UploadCompleteHook;
use MediaWiki\Linker\LinkTarget;
use MediaWiki\MediaWikiServices;
use MediaWiki\Page\Hook\ArticleProtectCompleteHook;
use MediaWiki\Page\Hook\PageDeleteCompleteHook;
use MediaWiki\Page\Hook\PageUndeleteCompleteHook;
use MediaWiki\Page\ProperPageIdentity;
use MediaWiki\Parser\Parser;
use MediaWiki\Permissions\Authority;
use MediaWiki\RenameUser\Hook\RenameUserCompleteHook;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Storage\EditResult;
use MediaWiki\Storage\Hook\PageSaveCompleteHook;
use MediaWiki\Title\Title;
use MediaWiki\User\Hook\UserGroupsChangedHook;
use MediaWiki\User\User;
use MediaWiki\User\UserGroupMembership;
use MediaWiki\User\UserIdentity;
use UploadBase;
use WikiFilePage;
use WikiPage;
/**
* Hooks for the Discord extension
*
* @file
* @ingroup Extensions
*/
class DiscordHooks {
/**
* Called when a page is created or edited
* @see https://www.mediawiki.org/wiki/Manual:Hooks/PageContentSaveComplete
*/
public static function onPageContentSaveComplete( &$wikiPage, &$user, $content, $summary, $isMinor, $isWatch, $section, &$flags, $revision, &$status, $baseRevId, $undidRevId ) {
global $wgDiscordNoBots, $wgDiscordNoMinor, $wgDiscordNoNull;
class DiscordHooks implements
PageSaveCompleteHook,
PageDeleteCompleteHook,
ArticleRevisionVisibilitySetHook,
ArticleProtectCompleteHook,
PageMoveCompleteHook,
LocalUserCreatedHook,
BlockIpCompleteHook,
UnblockUserCompleteHook,
UserGroupsChangedHook,
UploadCompleteHook,
FileDeleteCompleteHook,
FileUndeleteCompleteHook,
AfterImportPageHook,
ArticleMergeCompleteHook,
RenameUserCompleteHook,
PageUndeleteCompleteHook
{
private DiscordMessageSender $messageSender;
if ( DiscordUtils::isDisabled( 'PageContentSaveComplete', $wikiPage->getTitle()->getNamespace() ) ) {
return true;
}
public function __construct( DiscordMessageSender $messageSender ) {
$this->messageSender = $messageSender;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot edit
return true;
}
/**
* @param WikiPage $wikiPage
* @param UserIdentity $userIdentity
* @param string $summary
* @param int $flags
* @param RevisionRecord $revisionRecord
* @param EditResult $editResult
* @return bool
*/
public function onPageSaveComplete(
$wikiPage,
$userIdentity,
$summary,
$flags,
$revisionRecord,
$editResult
): bool {
global $wgDiscordNoBots, $wgDiscordNoMinor, $wgDiscordNoNull;
$hookName = 'PageSaveComplete';
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromUserIdentity( $userIdentity );
if ( $wgDiscordNoMinor && $isMinor ) {
// Don't continue, this is a minor edit
return true;
}
if ( DiscordUtils::isDisabled( $hookName, $wikiPage->getTitle()->getNamespace(), $user ) ) {
return true;
}
if ( $wgDiscordNoNull && ( !$revision || is_null( $status->getValue()['revision'] ) ) ) {
// Don't continue, this is a null edit
return true;
}
$isNew = $editResult->isNew();
if ( $wikiPage->getTitle()->inNamespace( NS_FILE ) ) {
// Don't continue, it's a file which onUploadComplete will handle instead
return true;
}
if (
( $wgDiscordNoBots && $user->isBot() ) ||
( $wgDiscordNoMinor && $revisionRecord->isMinor() ) ||
( $wgDiscordNoNull && $editResult->isNullEdit() ) ||
( $isNew && $wikiPage->getNamespace() === NS_FILE )
) {
return true;
}
$msg = wfMessage( 'discord-edit', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $wikiPage->getTitle(), $wikiPage->getTitle()->getFullUrl( '', '', $proto = PROTO_HTTP ) ),
DiscordUtils::createRevisionText( $revision ),
( $summary ? ('`' . $summary . '`' ) : '' ) )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
$msgKey = 'discord-msg-page-edited';
if ( $isNew ) {
$msgKey = 'discord-msg-page-created';
}
/**
* Called when a page is deleted
* @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticleDeleteComplete
*/
public static function onArticleDeleteComplete( &$article, User &$user, $reason, $id, $content, LogEntry $logEntry, $archivedRevisionCount ) {
global $wgDiscordNoBots, $wgDiscordNoMinor, $wgDiscordNoNull;
$msg = wfMessage( $msgKey, DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $wikiPage->getTitle(),
$wikiPage->getTitle()->getFullURL( '', false, PROTO_CANONICAL ) ),
DiscordUtils::createRevisionText( $revisionRecord ),
( $summary ? ( '`' . DiscordUtils::sanitiseText(
DiscordUtils::truncateText( $summary ) ) . '`' ) : '' ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
if ( DiscordUtils::isDisabled( 'ArticleDeleteComplete', $article->getTitle()->getNamespace() ) ) {
return true;
}
public function onPageDeleteComplete(
ProperPageIdentity $page,
Authority $deleter,
string $reason,
int $pageID,
RevisionRecord $deletedRev,
ManualLogEntry $logEntry,
int $archivedRevisionCount
): bool {
global $wgDiscordNoBots;
$hookName = 'PageDeleteComplete';
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return true;
}
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromUserIdentity( $deleter->getUser() );
$page = MediaWikiServices::getInstance()->getWikiPageFactory()->newFromTitle( $page );
$msg = wfMessage( 'discord-articledelete', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $article->getTitle(), $article->getTitle()->getFullUrl( '', '', $proto = PROTO_HTTP ) ),
( $reason ? ('`' . $reason . '`' ) : '' ),
$archivedRevisionCount)->text();
DiscordUtils::handleDiscord($msg);
return true;
}
if ( DiscordUtils::isDisabled( $hookName, $page->getNamespace(), $user ) ) {
return true;
}
/**
* Called when a page's revisions are restored
* @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticleUndelete
*/
public static function onArticleUndelete( Title $title, $create, $comment, $oldPageId, $restoredPages ) {
global $wgUser;
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return true;
}
if ( DiscordUtils::isDisabled( 'ArticleUndelete', $title->getNamespace() ) ) {
return true;
}
$msg = wfMessage( 'discord-msg-page-deleted', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $page->getTitle(),
$page->getTitle()->getFullURL( '', false, PROTO_CANONICAL ) ),
( $reason ? ( '`' . DiscordUtils::sanitiseText( DiscordUtils::truncateText( $reason ) ) . '`' ) : '' ),
$archivedRevisionCount )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
$msg = wfMessage( 'discord-articleundelete', DiscordUtils::createUserLinks( $wgUser ),
($create ? '' : wfMessage( 'discord-undeleterev' )->text() ),
DiscordUtils::createMarkdownLink( $title, $title->getFullUrl( '', '', $proto = PROTO_HTTP ) ),
( $comment ? ('`' . $comment . '`' ) : '' ))->text();
DiscordUtils::handleDiscord($msg);
return true;
}
public function onPageUndeleteComplete(
ProperPageIdentity $page,
Authority $restorer,
string $reason,
RevisionRecord $restoredRev,
ManualLogEntry $logEntry,
int $restoredRevisionCount,
bool $created,
array $restoredPageIds
): void {
global $wgDiscordNoBots;
$hookName = 'PageUndeleteComplete';
/**
* Called after committing revision visibility changes to the database
* @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticleRevisionVisibilitySet
*/
public static function onArticleRevisionVisibilitySet( &$title, $ids, $visibilityChangeMap ) {
global $wgUser;
$user = RequestContext::getMain()->getUser();
if ( DiscordUtils::isDisabled( 'ArticleRevisionVisibilitySet', $title->getNamespace() ) ) {
return true;
}
if ( DiscordUtils::isDisabled( $hookName, $page->getNamespace(), $user ) ) {
return;
}
$msg = wfMessage( 'discord-revvisibility', DiscordUtils::createUserLinks( $wgUser ),
count($visibilityChangeMap),
DiscordUtils::createMarkdownLink( $title, $title->getFullUrl( '', '', $proto = PROTO_HTTP ) ) )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return;
}
/**
* Called when a page is protected (or unprotected)
* @see https://www.mediawiki.org/wiki/Manual:Hooks/ArticleProtectComplete
*/
public static function onArticleProtectComplete( &$article, &$user, $protect, $reason ) {
global $wgDiscordNoBots;
$title = MediaWikiServices::getInstance()->getTitleFactory()->newFromPageIdentity( $page );
if ( DiscordUtils::isDisabled( 'ArticleProtectComplete', $article->getTitle()->getNamespace() ) ) {
return true;
}
$msg = wfMessage( 'discord-msg-page-undeleted', DiscordUtils::createUserLinks( $user ),
( $created ? '' : wfMessage( 'discord-msg-page-undeleted-revs' )->inContentLanguage()->text() ),
DiscordUtils::createMarkdownLink( $title, $title->getFullURL( '', false, PROTO_CANONICAL ) ),
( $reason ? ( '`' . DiscordUtils::sanitiseText(
DiscordUtils::truncateText( $reason ) ) . '`' ) : '' ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return true;
}
/**
* @param Title $title
* @param int[] $ids
* @param array $visibilityChangeMap
* @return bool
*/
public function onArticleRevisionVisibilitySet( $title, $ids, $visibilityChangeMap ): bool {
global $wgDiscordNoBots;
$hookName = 'ArticleRevisionVisibilitySet';
$msg = wfMessage( 'discord-articleprotect', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $article->getTitle(), $article->getTitle()->getFullUrl( '', '', $proto = PROTO_HTTP ) ),
( $reason ? ('`' . $reason . '`' ) : '' ),
implode(", ", $protect) )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
$user = RequestContext::getMain()->getUser();
/**
* Called when a page is moved
* @see https://www.mediawiki.org/wiki/Manual:Hooks/TitleMoveComplete
*/
public static function onTitleMoveComplete( Title &$title, Title &$newTitle, User $user, $oldid, $newid, $reason, Revision $revision ) {
global $wgDiscordNoBots;
if ( DiscordUtils::isDisabled( $hookName, $title->getNamespace(), $user ) ) {
return true;
}
if ( DiscordUtils::isDisabled( 'TitleMoveComplete', $title->getNamespace() ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return true;
}
$msg = wfMessage( 'discord-msg-rev-visibility-changed', DiscordUtils::createUserLinks( $user ),
count( $visibilityChangeMap ),
DiscordUtils::createMarkdownLink( $title,
$title->getFullURL( '', false, PROTO_CANONICAL ) ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
$msg = wfMessage( 'discord-titlemove', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $title, $title->getFullUrl( '', '', $proto = PROTO_HTTP ) ),
DiscordUtils::createMarkdownLink( $newTitle, $newTitle->getFullUrl( '', '', $proto = PROTO_HTTP ) ),
( $reason ? ('`' . $reason . '`' ) : '' ),
DiscordUtils::createRevisionText( $revision ) )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
/**
* @param WikiPage $wikiPage
* @param User $user
* @param array $protect
* @param string $reason
* @return bool
*/
public function onArticleProtectComplete( $wikiPage, $user, $protect, $reason ): bool {
global $wgDiscordNoBots;
$hookName = 'ArticleProtectComplete';
/**
* Called when a user is created
* @see https://www.mediawiki.org/wiki/Manual:Hooks/LocalUserCreated
*/
public static function onLocalUserCreated( $user, $autocreated ) {
if ( DiscordUtils::isDisabled( 'LocalUserCreated', NULL ) ) {
return true;
}
if ( DiscordUtils::isDisabled( $hookName, $wikiPage->getTitle()->getNamespace(), $user ) ) {
return true;
}
$msg = wfMessage( 'discord-localusercreated', DiscordUtils::createUserLinks( $user ) )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return true;
}
/**
* Called when a user is blocked
* @see https://www.mediawiki.org/wiki/Manual:Hooks/BlockIpComplete
*/
public static function onBlockIpComplete( Block $block, User $user ) {
if ( DiscordUtils::isDisabled( 'BlockIpComplete', NULL ) ) {
return true;
}
$msg = wfMessage( 'discord-msg-page-protect', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $wikiPage->getTitle(),
$wikiPage->getTitle()->getFullURL( '', false, PROTO_CANONICAL ) ),
( $reason ? ( '`' . DiscordUtils::sanitiseText( DiscordUtils::truncateText( $reason ) ) . '`' ) : '' ),
implode( ", ", $protect ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
$expiry = $block->getExpiry();
if ($expires = strtotime($expiry)) {
$expiryMsg = sprintf('%s', date( wfMessage( 'discord-blocktimeformat' )->text(), $expires));
} else {
$expiryMsg = $expiry;
}
/**
* @param LinkTarget $old
* @param LinkTarget $new
* @param UserIdentity $userIdentity
* @param int $pageid
* @param int $redirid
* @param string $reason
* @param RevisionRecord $revision
* @return bool
*/
public function onPageMoveComplete(
$old,
$new,
$userIdentity,
$pageid,
$redirid,
$reason,
$revision
): bool {
global $wgDiscordNoBots;
$hookName = 'PageMoveComplete';
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromUserIdentity( $userIdentity );
$msg = wfMessage( 'discord-blockipcomplete', DiscordUtils::createUserLinks( $user ), DiscordUtils::createUserLinks( $block->getTarget() ),
( $block->mReason ? ('`' . $block->mReason . '`' ) : '' ),
$expiryMsg )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
if ( DiscordUtils::isDisabled( $hookName, $old->getNamespace(), $user ) ) {
return true;
}
/**
* Called when a user is unblocked
* @see https://www.mediawiki.org/wiki/Manual:Hooks/UnblockUserComplete
*/
public static function onUnblockUserComplete( Block $block, User $user ) {
if ( DiscordUtils::isDisabled( 'UnblockUserComplete', NULL ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return true;
}
$msg = wfMessage( 'discord-unblockusercomplete', DiscordUtils::createUserLinks( $user ), DiscordUtils::createUserLinks( $block->getTarget() ) )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
$msg = wfMessage( 'discord-msg-page-moved', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $old,
Title::castFromLinkTarget( $old )->getFullURL( '', false, PROTO_CANONICAL ) ),
DiscordUtils::createMarkdownLink( $new,
Title::castFromLinkTarget( $new )->getFullURL( '', false, PROTO_CANONICAL ) ),
( $reason ? ( '`' . DiscordUtils::sanitiseText( DiscordUtils::truncateText( $reason ) ) . '`' ) : '' ),
DiscordUtils::createRevisionText( $revision ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* Called when a user's rights are changed
* @see https://www.mediawiki.org/wiki/Manual:Hooks/UserGroupsChanged
*/
public static function onUserGroupsChanged( User $user, array $added, array $removed, $performer, $reason ) {
if ( DiscordUtils::isDisabled( 'UserGroupsChanged', NULL ) ) {
return true;
}
/**
* @param User $user
* @param bool $autocreated
* @return bool
*/
public function onLocalUserCreated( $user, $autocreated ): bool {
$hookName = 'LocalUserCreated';
if ($performer === false) {
// Rights were changed by autopromotion, do nothing
return true;
}
if ( DiscordUtils::isDisabled( $hookName, null, $user ) ) {
return true;
}
$msg = wfMessage( 'discord-usergroupschanged', DiscordUtils::createUserLinks( $performer ),
DiscordUtils::createUserLinks( $user ),
( $reason ? ('`' . $reason . '`' ) : '' ),
( ( count($added) > 0 ) ? ( '+ ' . join(', ', $added) ) : ''),
( ( count($removed) > 0 ) ? ( '- ' . join(', ', $removed) ) : '' ) )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
if ( $user->isTemp() ) {
return true;
}
/**
* Called when a file upload is complete
* @see https://www.mediawiki.org/wiki/Manual:Hooks/UploadComplete
*/
public static function onUploadComplete( &$image ) {
if ( DiscordUtils::isDisabled( 'UploadComplete', NS_FILE ) ) {
return true;
}
$msg = wfMessage( 'discord-msg-user-registered',
DiscordUtils::createUserLinks( $user ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
$lf = $image->getLocalFile();
$user = $lf->getUser( $type = 'object' ); // only supported in MW 1.31+
$comment = $lf->getDescription();
$isNewRevision = count($lf->getHistory()) > 0;
/**
* @param DatabaseBlock $block
* @param User $user
* @param ?DatabaseBlock $priorBlock
* @return bool
*/
public function onBlockIpComplete( $block, $user, $priorBlock ): bool {
$hookName = 'BlockIpComplete';
$msg = wfMessage( 'discord-uploadcomplete', DiscordUtils::createUserLinks( $user ),
( $isNewRevision ? wfMessage( 'discord-uploadnewver' )->text() : '' ),
DiscordUtils::createMarkdownLink( $lf->getName(), $lf->getTitle()->getFullUrl( '', '', $proto = PROTO_HTTP ) ),
( $comment ? ('`' . $comment . '`' ) : '' ),
DiscordUtils::formatBytes($lf->getSize()),
$lf->getWidth(),
$lf->getHeight(),
$lf->getMimeType() )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
if ( DiscordUtils::isDisabled( $hookName, null, $user ) ) {
return true;
}
/**
* Called when a file is deleted
* @see https://www.mediawiki.org/wiki/Manual:Hooks/FileDeleteComplete
*/
public static function onFileDeleteComplete( $file, $oldimage, $article, $user, $reason ) {
if ( DiscordUtils::isDisabled( 'FileDeleteComplete', NS_FILE ) ) {
return true;
}
$expiry = $block->getExpiry();
$expiryAsUnix = strtotime( $expiry );
if ( $expiryAsUnix ) {
$expiryMsg = sprintf( '%s',
date( wfMessage( 'discord-msg-user-block-timeformat' )->inContentLanguage()->text(), $expiryAsUnix ) );
} else {
$expiryMsg = $expiry;
}
if ( $article ) {
// Entire page was deleted, onArticleDeleteComplete will handle this
return true;
}
$target = $block->getTargetUserIdentity();
if ( $target === null ) {
$target = $block->getTargetName();
}
$msg = wfMessage( 'discord-filedeletecomplete', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $file->getName(), $file->getTitle()->getFullUrl( '', '', $proto = PROTO_HTTP ) ),
( $reason ? ('`' . $reason . '`' ) : '' ) )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
$msgName = $block->isSitewide() ? 'discord-msg-user-block' : 'discord-msg-user-block-partial';
/**
* Called when a file is restored
* @see https://www.mediawiki.org/wiki/Manual:Hooks/FileUndeleteComplete
*/
public static function onFileUndeleteComplete( $title, $fileVersions, $user, $reason ) {
if ( DiscordUtils::isDisabled( 'FileUndeleteComplete', NS_FILE ) ) {
return true;
}
$msg = wfMessage( $msgName, DiscordUtils::createUserLinks( $user ),
DiscordUtils::createUserLinks( $target ),
( $block->getReasonComment()->text ? ( '`' . DiscordUtils::sanitiseText(
DiscordUtils::truncateText( $block->getReasonComment()->text ) ) . '`' ) : '' ),
$expiryMsg )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
$msg = wfMessage( 'discord-fileundeletecomplete', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $title, $title->getFullUrl( '', '', $proto = PROTO_HTTP ) ),
( $reason ? ('`' . $reason . '`' ) : '' ) )->text();
DiscordUtils::handleDiscord($msg);
return true;
}
/**
* @param DatabaseBlock $block
* @param User $user
* @return bool
*/
public function onUnblockUserComplete( $block, $user ): bool {
$hookName = 'UnblockUserComplete';
if ( DiscordUtils::isDisabled( $hookName, null, $user ) ) {
return true;
}
$target = $block->getTargetUserIdentity();
if ( $target === null ) {
$target = $block->getTargetName();
}
$msg = wfMessage( 'discord-msg-user-unblock', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createUserLinks( $target ) )->inContentLanguage()->text();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param User|UserIdentity $user
* @param string[] $added
* @param string[] $removed
* @param User|false $performer
* @param string|false $reason
* @param UserGroupMembership[] $oldUGMs
* @param UserGroupMembership[] $newUGMs
* @return bool
*/
public function onUserGroupsChanged( $user, $added, $removed, $performer, $reason, $oldUGMs, $newUGMs ): bool {
$hookName = 'UserGroupsChanged';
if ( DiscordUtils::isDisabled( $hookName, null, $performer ) ) {
return true;
}
if ( $performer === false ) {
// Rights were changed by autopromotion, do nothing
return true;
}
$msg = wfMessage( 'discord-msg-user-groups-changed', DiscordUtils::createUserLinks( $performer ),
DiscordUtils::createUserLinks( $user ),
( $reason ? ( '`' . DiscordUtils::sanitiseText( DiscordUtils::truncateText( $reason ) ) . '`' ) : '' ),
( ( count( $added ) > 0 ) ? ( '+ ' . implode( ', ', $added ) ) : '' ),
( ( count( $removed ) > 0 ) ? ( '- ' . implode( ', ', $removed ) ) : '' ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param UploadBase $uploadBase
* @return bool
*/
public function onUploadComplete( $uploadBase ): bool {
global $wgDiscordNoBots;
$hookName = 'UploadComplete';
$lf = $uploadBase->getLocalFile();
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromUserIdentity( $lf->getUploader() );
if ( DiscordUtils::isDisabled( $hookName, NS_FILE, $user ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return true;
}
$comment = $lf->getDescription();
$isNewRevision = count( $lf->getHistory() ) > 0;
$msg = wfMessage( 'discord-msg-file-upload', DiscordUtils::createUserLinks( $user ),
( $isNewRevision ? wfMessage( 'discord-msg-file-upload-new' )->inContentLanguage()->text() : '' ),
DiscordUtils::createMarkdownLink( $lf->getName(),
$lf->getTitle()->getFullURL( '', false, PROTO_CANONICAL ) ),
( $comment ? ( '`' . DiscordUtils::sanitiseText( DiscordUtils::truncateText( $comment ) ) . '`' ) : '' ),
DiscordUtils::formatBytes( $lf->getSize() ),
$lf->getWidth(),
$lf->getHeight(),
$lf->getMimeType() )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param LocalFile $file
* @param string|null $oldimage
* @param WikiFilePage|null $article
* @param User $user
* @param string $reason
* @return bool
*/
public function onFileDeleteComplete( $file, $oldimage, $article, $user, $reason ): bool {
global $wgDiscordNoBots;
$hookName = 'FileDeleteComplete';
if ( DiscordUtils::isDisabled( $hookName, NS_FILE, $user ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return true;
}
if ( $article ) {
// Entire page was deleted, onArticleDeleteComplete will handle this
return true;
}
$msg = wfMessage( 'discord-msg-file-delete', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $file->getName(),
$file->getTitle()->getFullURL( '', false, PROTO_CANONICAL ) ),
( $reason ? ( '`' . DiscordUtils::sanitiseText(
DiscordUtils::truncateText( $reason ) ) . '`' ) : '' ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param Title $title
* @param int[] $fileVersions
* @param User $user
* @param string $reason
* @return bool
*/
public function onFileUndeleteComplete( $title, $fileVersions, $user, $reason ): bool {
global $wgDiscordNoBots;
$hookName = 'FileUndeleteComplete';
if ( DiscordUtils::isDisabled( $hookName, NS_FILE, $user ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot change
return true;
}
$msg = wfMessage( 'discord-msg-file-undelete', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $title, $title->getFullURL( '', false, PROTO_CANONICAL ) ),
( $reason ? ( '`' . DiscordUtils::sanitiseText(
DiscordUtils::truncateText( $reason ) ) . '`' ) : '' ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param Title $title
* @param ForeignTitle $foreignTitle
* @param int $revCount
* @param int $sRevCount
* @param array $pageInfo
* @return bool
*/
public function onAfterImportPage( $title, $foreignTitle, $revCount, $sRevCount, $pageInfo ): bool {
global $wgDiscordNoBots;
$hookName = 'AfterImportPage';
$user = RequestContext::getMain()->getUser();
if ( DiscordUtils::isDisabled( $hookName, $title->getNamespace(), $user ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot
return true;
}
$msg = wfMessage( 'discord-msg-import', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $title, $title->getFullURL( '', false, PROTO_CANONICAL ) ),
$revCount, $sRevCount )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param Title $targetTitle
* @param Title $destTitle
* @return bool
*/
public function onArticleMergeComplete( $targetTitle, $destTitle ): bool {
global $wgDiscordNoBots;
$hookName = 'ArticleMergeComplete';
$user = RequestContext::getMain()->getUser();
if ( DiscordUtils::isDisabled( $hookName, $destTitle->getNamespace(), $user ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot
return true;
}
$msg = wfMessage( 'discord-msg-page-merge', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $targetTitle, $targetTitle->getFullURL( '', false, PROTO_CANONICAL ) ),
DiscordUtils::createMarkdownLink( $destTitle,
$destTitle->getFullURL( '', false, PROTO_CANONICAL ) ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param null $output
* @param Title $title
* @param int $rev_id
* @param mixed $content
* @return bool
* @see https://github.com/wikimedia/mediawiki-extensions-ApprovedRevs/blob/REL1_45/includes/ApprovedRevs.php#L602
*/
public function onApprovedRevsRevisionApproved( $output, $title, $rev_id, $content ): bool {
global $wgDiscordNoBots;
$hookName = 'ApprovedRevsRevisionApproved';
$user = RequestContext::getMain()->getUser();
if ( DiscordUtils::isDisabled( $hookName, $title->getNamespace(), $user ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot
return true;
}
// Get the revision being approved here
$rev = MediaWikiServices::getInstance()->getRevisionLookup()->getRevisionByTitle( $title, $rev_id );
$revLink = $title->getFullURL( '', false, PROTO_CANONICAL );
$revAuthor = DiscordUtils::createUserLinks( $rev->getUser( RevisionRecord::RAW ) );
$msg = wfMessage( 'discord-msg-ext-approvedrevs-approved', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $title, $title->getFullURL( '', false, PROTO_CANONICAL ) ),
DiscordUtils::createMarkdownLink( $rev_id, $revLink ),
$revAuthor )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param null $output
* @param Title $title
* @param mixed $content
* @return bool
* @see https://github.com/wikimedia/mediawiki-extensions-ApprovedRevs/blob/REL1_45/includes/ApprovedRevs.php#L712
*/
public function onApprovedRevsRevisionUnapproved( $output, $title, $content ): bool {
global $wgDiscordNoBots;
$hookName = 'ApprovedRevsRevisionUnapproved';
$user = RequestContext::getMain()->getUser();
if ( DiscordUtils::isDisabled( $hookName, $title->getNamespace(), $user ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot
return true;
}
$msg = wfMessage( 'discord-msg-ext-approvedrevs-unapproved', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $title,
$title->getFullURL( '', false, PROTO_CANONICAL ) ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param Parser $parser
* @param Title $title
* @param string $timestamp
* @param string $sha1
* @return bool
* @see https://github.com/wikimedia/mediawiki-extensions-ApprovedRevs/blob/REL1_45/includes/ApprovedRevs.php#L827
*/
public function onApprovedRevsFileRevisionApproved( $parser, $title, $timestamp, $sha1 ): bool {
global $wgDiscordNoBots;
$hookName = 'ApprovedRevsFileRevisionApproved';
$user = RequestContext::getMain()->getUser();
if ( DiscordUtils::isDisabled( $hookName, $title->getNamespace(), $user ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot
return true;
}
$imagepage = ImagePage::newFromID( $title->getArticleID() );
$displayedFile = $imagepage->getDisplayedFile();
// getFullURL doesn't work quite the same on File classes
$displayedFileUrl = $displayedFile->getCanonicalUrl();
$uploader = MediaWikiServices::getInstance()->getUserFactory()->newFromUserIdentity(
$displayedFile->getUploader() );
$msg = wfMessage( 'discord-msg-ext-approvedrevs-approved-file', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $title, $title->getFullURL( '', false, PROTO_CANONICAL ) ),
DiscordUtils::createMarkdownLink( 'direct', $displayedFileUrl ),
DiscordUtils::createUserLinks( $uploader ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param Parser $parser
* @param Title $title
* @return bool
* @see https://github.com/wikimedia/mediawiki-extensions-ApprovedRevs/blob/REL1_45/includes/ApprovedRevs.php#L865
*/
public function onApprovedRevsFileRevisionUnapproved( $parser, $title ): bool {
global $wgDiscordNoBots;
$hookName = 'ApprovedRevsFileRevisionUnapproved';
$user = RequestContext::getMain()->getUser();
if ( DiscordUtils::isDisabled( $hookName, $title->getNamespace(), $user ) ) {
return true;
}
if ( $wgDiscordNoBots && $user->isBot() ) {
// Don't continue, this is a bot
return true;
}
$msg = wfMessage( 'discord-msg-ext-approvedrevs-unapproved-file', DiscordUtils::createUserLinks( $user ),
DiscordUtils::createMarkdownLink( $title,
$title->getFullURL( '', false, PROTO_CANONICAL ) ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
return true;
}
/**
* @param int $uid
* @param string $old
* @param string $new
* @return void
*/
public function onRenameUserComplete( $uid, $old, $new ): void {
$hookName = 'RenameUserComplete';
$user = RequestContext::getMain()->getUser();
if ( DiscordUtils::isDisabled( $hookName, null, null ) ) {
return;
}
$renamedUserAsTitle = MediaWikiServices::getInstance()->getUserFactory()->newFromName( $new )->getUserPage();
$msg = wfMessage( 'discord-msg-user-rename', DiscordUtils::createUserLinks( $user ),
"*$old*",
DiscordUtils::createMarkdownLink( $new,
$renamedUserAsTitle->getFullURL( '', false, PROTO_CANONICAL ) ) )->inContentLanguage()->plain();
$this->messageSender->sendToDiscord( $hookName, $msg );
}
}
+94
View File
@@ -0,0 +1,94 @@
<?php
namespace MediaWiki\Extension\Discord;
use Exception;
use MediaWiki\Deferred\DeferredUpdates;
use MediaWiki\Http\HttpRequestFactory;
use Wikimedia\Http\MultiHttpClient;
class DiscordMessageSender {
public MultiHttpClient $multiHttpClient;
public function __construct( HttpRequestFactory $httpRequestFactory ) {
$this->multiHttpClient = $httpRequestFactory->createMultiClient( [
'connTimeout' => 10,
'reqTimeout' => 10
] );
}
/**
* Sends a message to Discord, based on the extension's configuration.
* @param string $hookName
* @param string $msg
* @return void
*/
public function sendToDiscord( string $hookName, string $msg ) {
global $wgDiscordWebhookURL, $wgDiscordEmojis, $wgDiscordUseEmojis, $wgDiscordPrependTimestamp;
if ( !$wgDiscordWebhookURL ) {
return;
}
$urls = [];
if ( is_array( $wgDiscordWebhookURL ) ) {
$urls = array_merge( $urls, $wgDiscordWebhookURL );
} elseif ( is_string( $wgDiscordWebhookURL ) ) {
$urls[] = $wgDiscordWebhookURL;
} else {
wfDebugLog( 'discord',
'The value of $wgDiscordWebhookURL is not valid and therefore no webhooks could be sent.' );
return;
}
// Strip whitespace to just one space
$stripped = preg_replace( '/\s+/', ' ', $msg );
if ( $wgDiscordPrependTimestamp ) {
$dateString = gmdate( wfMessage( 'discord-timestampformat' )->inContentLanguage()->text() );
$stripped = $dateString . ' ' . $stripped;
}
if ( $wgDiscordUseEmojis ) {
$emoji = $wgDiscordEmojis[$hookName];
$stripped = $emoji . ' ' . $stripped;
}
$reqs = [];
foreach ( $urls as $url ) {
$reqs[] = $this->buildRequest( $url, $stripped );
}
DeferredUpdates::addCallableUpdate( function () use ( $reqs ) {
try {
$this->multiHttpClient->runMulti( $reqs );
} catch ( Exception ) {
// TODO: better logging
}
} );
}
/**
* Builds a request for use with MultiHttpClient
* @param string $url
* @param string $msg
* @return array
*/
private function buildRequest( string $url, string $msg ): array {
return [
'method' => 'POST',
'url' => $url,
'headers' => [
'Content-Type' => 'application/json',
'User-Agent' => 'mw-discord/1.2 (github.com/jayktaylor)'
],
'body' => json_encode( [
'content' => $msg,
'allowed_mentions' => [
'parse' => []
]
] )
];
}
}
+199
View File
@@ -0,0 +1,199 @@
<?php
namespace MediaWiki\Extension\Discord;
use MediaWiki\MediaWikiServices;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Title\Title;
use MediaWiki\User\User;
use MediaWiki\User\UserIdentity;
class DiscordUtils {
/**
* Checks if criteria is met for this action to be cancelled
* @param string $hook
* @param int|null $ns
* @param User|UserIdentity|null $user
* @return bool
*/
public static function isDisabled(
string $hook, int|null $ns, User|UserIdentity|null $user
): bool {
global $wgDiscordDisabledHooks, $wgDiscordDisabledNS, $wgDiscordDisabledUsers;
if ( is_array( $wgDiscordDisabledHooks ) ) {
if ( in_array( strtolower( $hook ), array_map( 'strtolower', $wgDiscordDisabledHooks ) ) ) {
// Hook is disabled, return true
return true;
}
} else {
wfDebugLog( 'discord',
'The value of $wgDiscordDisabledHooks is not valid and therefore all hooks are enabled.' );
}
if ( is_array( $wgDiscordDisabledNS ) ) {
if ( $ns !== null ) {
$ns = (int)$ns;
if ( in_array( $ns, $wgDiscordDisabledNS ) ) {
// Namespace is disabled, return true
return true;
}
}
} else {
wfDebugLog( 'discord',
'The value of $wgDiscordDisabledNS is not valid and therefore all namespaces are enabled.' );
}
if ( is_array( $wgDiscordDisabledUsers ) ) {
if ( $user !== null ) {
if ( $user instanceof UserIdentity ) {
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromUserIdentity( $user );
}
if ( $user instanceof User ) {
if ( in_array( $user->getName(), $wgDiscordDisabledUsers ) ) {
// User shouldn't trigger a message, return true
return true;
}
}
}
} else {
wfDebugLog( 'discord',
'The value of $wgDiscordDisabledUsers is not valid and therefore all users can trigger messages.' );
}
return false;
}
/**
* Creates a formatted markdown link based on text and given URL
* @param string $text
* @param string $url
* @return string
*/
public static function createMarkdownLink( string $text, string $url ): string {
global $wgDiscordSuppressPreviews;
return "[" . $text . "]" . '(' . ( $wgDiscordSuppressPreviews ? '<' : '' ) .
self::encodeURL( $url ) . ( $wgDiscordSuppressPreviews ? '>' : '' ) . ')';
}
/**
* Creates links for a specific MediaWiki User object
* @param User|UserIdentity|string $user
* @return string
*/
public static function createUserLinks( User|UserIdentity|string $user ): string {
global $wgDiscordMaxCharsUsernames;
if ( $user instanceof UserIdentity ) {
// If we were passed a UserIdentity object, get the relevant user.
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromUserIdentity( $user );
}
if ( $user instanceof User ) {
$isAnon = $user->isAnon();
$contribs = Title::newFromText( "Special:Contributions/" . $user );
$user_abbr = strval( $user );
if ( $wgDiscordMaxCharsUsernames ) {
if ( strlen( $user_abbr ) > $wgDiscordMaxCharsUsernames ) {
$user_abbr = substr( $user_abbr, 0, $wgDiscordMaxCharsUsernames );
$user_abbr = $user_abbr . '...';
}
}
$userPage = self::createMarkdownLink( $user_abbr, ( $isAnon ? $contribs : $user->getUserPage() )
->getFullURL( '', false, PROTO_CANONICAL ) );
$userTalk = self::createMarkdownLink( wfMessage( 'discord-talk' )->inContentLanguage()->text(),
$user->getTalkPage()->getFullURL( '', false, PROTO_CANONICAL ) );
$userContribs = self::createMarkdownLink( wfMessage( 'discord-contribs' )->inContentLanguage()->text(),
$contribs->getFullURL( '', false, PROTO_CANONICAL ) );
$text = wfMessage( 'discord-userlinks', $userPage, $userTalk, $userContribs )->inContentLanguage()->text();
} else {
// If we were given a string, handle this differently.
$text = wfMessage( 'discord-userlinks', $user, 'n/a', 'n/a' )->inContentLanguage()->text();
}
return $text;
}
/**
* Creates formatted text for a specific Revision object
* @param RevisionRecord $revision
* @return string
*/
public static function createRevisionText( RevisionRecord $revision ): string {
$diff = self::createMarkdownLink( wfMessage( 'discord-diff' )->inContentLanguage()->text(),
Title::newFromLinkTarget( $revision->getPageAsLinkTarget() )->getFullURL(
[ 'diff' => 'prev', 'oldid' => $revision->getId() ], false, PROTO_CANONICAL ) );
$minor = '';
$size = '';
if ( $revision->isMinor() ) {
$minor .= wfMessage( 'discord-minor' )->inContentLanguage()->text();
}
$parentId = $revision->getParentId();
if ( $parentId ) {
$parent = MediaWikiServices::getInstance()->getRevisionLookup()->getRevisionById( $parentId );
if ( $parent ) {
$size .= wfMessage( 'discord-size', sprintf( "%+d", $revision->getSize() - $parent->getSize() ) )
->inContentLanguage()->text();
}
}
if ( $size == '' ) {
$size .= wfMessage( 'discord-size', sprintf( "%d", $revision->getSize() ) )->inContentLanguage()->text();
}
return wfMessage( 'discord-revisionlinks', $diff, $minor, $size )->inContentLanguage()->text();
}
/**
* Strip bad characters from a URL
* @param string $url
* @return string
*/
public static function encodeURL( string $url ): string {
$url = str_replace( " ", "%20", $url );
$url = str_replace( "(", "%28", $url );
return str_replace( ")", "%29", $url );
}
/**
* Formats bytes to a string representing B, KB, MB, GB, TB
* @param int $bytes
* @param ?int $precision
* @return string
*/
public static function formatBytes( int $bytes, ?int $precision = 2 ): string {
$units = [ 'B', 'KB', 'MB', 'GB', 'TB' ];
$bytes = max( $bytes, 0 );
$pow = floor( ( $bytes ? log( $bytes ) : 0 ) / log( 1024 ) );
$pow = min( $pow, count( $units ) - 1 );
$bytes /= ( 1 << ( 10 * $pow ) );
return round( $bytes, $precision ) . ' ' . $units[$pow];
}
/**
* Truncate text to maximum allowed characters
* @param string $text
* @return string
*/
public static function truncateText( string $text ): string {
global $wgDiscordMaxChars;
if ( $wgDiscordMaxChars ) {
if ( strlen( $text ) > $wgDiscordMaxChars ) {
$text = substr( $text, 0, $wgDiscordMaxChars );
$text = $text . '...';
}
}
return $text;
}
/**
* Sanitise text input to remove the potential for abuse of Discord's role pings.
* @param string $text
* @return string
*/
public static function sanitiseText( string $text ): string {
return preg_replace( '/([`@])/', '', $text );
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace MediaWiki\Extension\Discord;
use MediaWiki\MediaWikiServices;
return [
'Discord.DiscordMessageSender' => static function ( MediaWikiServices $services ): DiscordMessageSender {
return new DiscordMessageSender(
$services->getHttpRequestFactory()
);
}
];
-168
View File
@@ -1,168 +0,0 @@
<?php
class DiscordUtils {
/**
* Checks if criteria is met for this action to be cancelled
*/
public static function isDisabled ( $hook, $ns ) {
global $wgDiscordDisabledHooks, $wgDiscordDisabledNS;
if ( is_array( $wgDiscordDisabledHooks ) ) {
if ( in_array( strtolower( $hook ), array_map( 'strtolower', $wgDiscordDisabledHooks ) ) ) {
// Hook is disabled, return true
return true;
}
} else {
wfDebugLog( 'discord', 'The value of $wgDiscordDisabledHooks is not valid and therefore all hooks are enabled.' );
}
if ( is_array( $wgDiscordDisabledNS ) ) {
if ( !is_null( $ns ) ) {
$ns = (int)$ns;
if ( in_array( $ns, $wgDiscordDisabledNS ) ) {
// Namespace is disabled, return true
return true;
}
}
} else {
wfDebugLog( 'discord', 'The value of $wgDiscordDisabledNS is not valid and therefore all namespaces are enabled.' );
}
return false;
}
/**
* Handles sending a webhook to Discord using cURL
*/
public static function handleDiscord ($msg) {
global $wgDiscordWebhookURL;
if ( !$wgDiscordWebhookURL ) {
// There's nothing in here, so we won't do anything
return false;
}
$urls = [];
if ( is_array( $wgDiscordWebhookURL ) ) {
$urls = array_merge($urls, $wgDiscordWebhookURL);
} else if ( is_string($wgDiscordWebhookURL) ) {
$urls[] = $wgDiscordWebhookURL;
} else {
wfDebugLog( 'discord', 'The value of $wgDiscordWebhookURL is not valid and therefore no webhooks could be sent.' );
return false;
}
// Strip whitespace to just one space
$stripped = preg_replace('/\s+/', ' ', $msg);
DeferredUpdates::addCallableUpdate( function() use ( $stripped, $urls ) {
$json_data = [ 'content' => "$stripped" ];
$json = json_encode($json_data);
// Set up cURL multi handlers
$c_handlers = [];
$result = [];
$mh = curl_multi_init();
foreach ($urls as &$value) {
$c_handlers[$value] = curl_init( $value );
curl_setopt( $c_handlers[$value], CURLOPT_POST, 1 ); // Send as a POST request
curl_setopt( $c_handlers[$value], CURLOPT_POSTFIELDS, $json ); // Send the JSON in the POST request
curl_setopt( $c_handlers[$value], CURLOPT_FOLLOWLOCATION, 1 );
curl_setopt( $c_handlers[$value], CURLOPT_HEADER, 0 );
curl_setopt( $c_handlers[$value], CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $c_handlers[$value], CURLOPT_CONNECTTIMEOUT, 10 ); // Add a timeout for connecting to the site
curl_setopt( $c_handlers[$value], CURLOPT_TIMEOUT, 20 ); // Do not allow cURL to run for a long time
curl_setopt( $c_handlers[$value], CURLOPT_USERAGENT, 'mw-discord/1.0 (github.com/jaydenkieran)' ); // Add a unique user agent
curl_multi_add_handle( $mh, $c_handlers[$value] );
$response = curl_exec( $ch );
}
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running);
// Remove all handlers and then close the multi handler
foreach($c_handlers as $k => $ch) {
$result[$k] = curl_multi_getcontent($ch);
curl_multi_remove_handle($mh, $ch);
}
curl_multi_close($mh);
} );
return true;
}
/**
* Creates a formatted markdown link based on text and given URL
*/
public static function createMarkdownLink ($text, $url) {
global $wgDiscordSuppressPreviews;
return "[" . $text . "]" . '(' . ($wgDiscordSuppressPreviews ? '<' : '') . self::encodeURL($url) . ($wgDiscordSuppressPreviews ? '>' : '') . ')';
}
/**
* Creates links for a specific MediaWiki User object
*/
public static function createUserLinks ($user) {
$userPage = DiscordUtils::createMarkdownLink( $user, $user->getUserPage()->getFullUrl( '', '', $proto = PROTO_HTTP ) );
$userTalk = DiscordUtils::createMarkdownLink( wfMessage( 'discord-talk' )->text(), $user->getTalkPage()->getFullUrl( '', '', $proto = PROTO_HTTP ) );
$userContribs = DiscordUtils::createMarkdownLink( wfMessage( 'discord-contribs' )->text(), Title::newFromText("Special:Contributions/" . $user)->getFullURL( '', '', $proto = PROTO_HTTP ) );
$text = wfMessage( 'discord-userlinks', $userPage, $userTalk, $userContribs )->text();
return $text;
}
/**
* Creates formatted text for a specific Revision object
*/
public static function createRevisionText ($revision) {
$diff = DiscordUtils::createMarkdownLink( wfMessage( 'discord-diff' )->text(), $revision->getTitle()->getFullUrl("diff=prev", ["oldid" => $revision->getID()], $proto = PROTO_HTTP) );
$minor = '';
$size = '';
if ( $revision->isMinor() ) {
$minor .= wfMessage( 'discord-minor' )->text();
}
$previous = $revision->getPrevious();
if ( $previous ) {
$size .= wfMessage( 'discord-size', sprintf( "%+d", $revision->getSize() - $previous->getSize() ) )->text();
} else if ( $revision->getParentId() ) {
// Try and get the parent revision based on the ID, if we can
$previous = Revision::newFromId( $revision->getParentId() );
if ($previous) {
$size .= wfMessage( 'discord-size', sprintf( "%+d", $revision->getSize() - $previous->getSize() ) )->text();
}
}
$text = wfMessage( 'discord-revisionlinks', $diff, $minor, $size )->text();
return $text;
}
/**
* 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;
}
/**
* Formats bytes to a string representing B, KB, MB, GB, TB
*/
public static function formatBytes($bytes, $precision = 2) {
$units = array('B', 'KB', 'MB', 'GB', 'TB');
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= (1 << (10 * $pow));
return round($bytes, $precision) . ' ' . $units[$pow];
}
}
?>
-20
View File
@@ -1,20 +0,0 @@
<?php
require "src/Utils.php";
class UtilsTests extends PHPUnit_Framework_TestCase {
public function testCreateMarkdownLink()
{
$link = DiscordUtils::CreateMarkdownLink("Link", "https://example.com");
$this->assertEquals("[Link](https://example.com)", $link);
}
public function testRemoveMultipleSlashes()
{
$url = DiscordUtils::RemoveMultipleSlashes("https://example.com/page/page2//page3/page4//page5//");
$this->assertEquals("https://example.com/page/page2/page3/page4/page5/", $url);
}
}
?>