소스 검색

multiple improvements

Markus-Rost 4 년 전
부모
커밋
fd4cbef89f
14개의 변경된 파일106개의 추가작업 그리고 53개의 파일을 삭제
  1. 7 1
      README.md
  2. 3 3
      bot.js
  3. 2 1
      cmds/eval.js
  4. 2 1
      cmds/link.js
  5. 4 3
      cmds/patreon.js
  6. 2 2
      cmds/settings.js
  7. 2 1
      cmds/verification.js
  8. 7 3
      cmds/wiki/fandom.js
  9. 7 3
      cmds/wiki/gamepedia.js
  10. 2 2
      functions/discussion.js
  11. 16 0
      privacy.md
  12. 16 9
      util/database.js
  13. 34 22
      util/default.json
  14. 2 2
      util/newMessage.js

+ 7 - 1
README.md

@@ -1,5 +1,4 @@
 # Wiki-Bot
-<a href="https://top.gg/bot/461189216198590464"><img align="right" src="https://top.gg/api/widget/461189216198590464.svg" alt="Wiki-Bot"></a>
 **Wiki-Bot** is a bot for [Discord](https://discord.com/) with the purpose to easily link to [Gamepedia](https://www.gamepedia.com/) and [Fandom](https://www.fandom.com/) wikis.
 <br>He resolves redirects and follows interwiki links.
 <br>**Wiki-Bot** has translations for English, German, French, Dutch, Polish, Portuguese, Russian, Turkish and Chinese.
@@ -77,3 +76,10 @@ See the [admin commands](#admin) or `!wiki help verification` on how to change t
 ## Voice Channel
 **Wiki-Bot** is able to give everyone in a voice channel a specific role. This allows for the creation of channels only visible or writable when in a specific voice channel.
 <br>Use `!wiki voice` to get the format for the role name.
+
+## Bot Lists
+[![Wiki-Bot](https://botsfordiscord.com/api/bot/461189216198590464/widget)](https://botsfordiscord.com/bot/461189216198590464)
+[![Wiki-Bot](https://discord.boats/api/widget/461189216198590464)](https://discord.boats/bot/461189216198590464)
+[![Wiki-Bot](https://top.gg/api/widget/461189216198590464.svg)](https://top.gg/bot/461189216198590464)
+
+[Privacy Policy](privacy.md)

+ 3 - 3
bot.js

@@ -106,7 +106,7 @@ String.prototype.toLink = function(title = '', querystring = '', fragment = '',
 	if ( this.isFandom() ) return this + 'wiki/' + title.toTitle(isMarkdown) + linksuffix;
 	let project = wikiProjects.find( project => this.split('/')[2].endsWith( project.name ) );
 	if ( project ) {
-		let regex = this.match( new RegExp( project.regex ) );
+		let regex = this.match( new RegExp( '^https://' + project.regex + project.scriptPath + '$' ) );
 		if ( regex ) return 'https://' + regex[1] + project.articlePath + title.toTitle(isMarkdown, project.articlePath.includes( '?' )) + ( project.articlePath.includes( '?' ) && linksuffix.startsWith( '?' ) ? '&' + linksuffix.substring(1) : linksuffix );
 	}
 	return this + 'index.php?title=' + title.toTitle(isMarkdown, true) + ( linksuffix.startsWith( '?' ) ? '&' + linksuffix.substring(1) : linksuffix );
@@ -192,7 +192,7 @@ Discord.MessageReaction.prototype.removeEmoji = function() {
 
 Discord.Message.prototype.sendChannel = function(content, options = {}, ignorePause = false) {
 	if ( this.channel.type !== 'text' || !pause[this.guild.id] || ( ignorePause && ( this.isAdmin() || this.isOwner() ) ) ) {
-		if ( !options.allowedMentions ) options.allowedMentions = {parse:[]};
+		if ( !options.allowedMentions ) options.allowedMentions = {users:[this.author.id]};
 		return this.channel.send(content, options).then( msg => {
 			if ( msg.length ) msg.forEach( message => message.allowDelete(this.author.id) );
 			else msg.allowDelete(this.author.id);
@@ -208,7 +208,7 @@ Discord.Message.prototype.sendChannel = function(content, options = {}, ignorePa
 };
 
 Discord.Message.prototype.sendChannelError = function(content, options = {}) {
-	if ( !options.allowedMentions ) options.allowedMentions = {parse:[]};
+	if ( !options.allowedMentions ) options.allowedMentions = {users:[this.author.id]};
 	return this.channel.send(content, options).then( msg => {
 		if ( msg.length ) msg.forEach( message => {
 			message.reactEmoji('error');

+ 2 - 1
cmds/eval.js

@@ -2,6 +2,7 @@ const util = require('util');
 util.inspect.defaultOptions = {compact:false,breakLength:Infinity};
 
 const Discord = require('discord.js');
+const {limit: {verification: verificationLimit, rcgcdw: rcgcdwLimit}} = require('../util/default.json');
 var db = require('../util/database.js');
 
 async function cmd_eval(lang, msg, args, line, wiki) {
@@ -73,7 +74,7 @@ function removePatreons(guild, msg) {
 				console.log( '- Error while getting the verifications: ' + dberror );
 				return dberror;
 			}
-			var ids = rows.slice(10).map( row => row.configid );
+			var ids = rows.slice(verificationLimit.default).map( row => row.configid );
 			if ( ids.length ) db.run( 'DELETE FROM verification WHERE guild = ? AND configid IN (' + ids.map( configid => '?' ).join(', ') + ')', [guild, ...ids], function (error) {
 				if ( error ) {
 					console.log( '- Error while deleting the verifications: ' + error );

+ 2 - 1
cmds/link.js

@@ -1,6 +1,7 @@
 const check_wiki = {
 	fandom: require('./wiki/fandom.js'),
-	gamepedia: require('./wiki/gamepedia.js')
+	gamepedia: require('./wiki/gamepedia.js'),
+	test: require('./test.js').run
 };
 const help_setup = require('../functions/helpsetup.js');
 

+ 4 - 3
cmds/patreon.js

@@ -1,3 +1,4 @@
+const {limit: {verification: verificationLimit, rcgcdw: rcgcdwLimit}} = require('../util/default.json');
 var db = require('../util/database.js');
 
 function cmd_patreon(lang, msg, args, line, wiki) {
@@ -67,7 +68,7 @@ function cmd_patreon(lang, msg, args, line, wiki) {
 					console.log( '- Error while getting the verifications: ' + dberror );
 					return dberror;
 				}
-				var ids = rows.slice(10).map( row => row.configid );
+				var ids = rows.slice(verificationLimit.default).map( row => row.configid );
 				if ( ids.length ) db.run( 'DELETE FROM verification WHERE guild = ? AND configid IN (' + ids.map( configid => '?' ).join(', ') + ')', [args[1], ...ids], function (error) {
 					if ( error ) {
 						console.log( '- Error while deleting the verifications: ' + error );
@@ -149,7 +150,7 @@ function cmd_patreon(lang, msg, args, line, wiki) {
 					msg.replyMsg( 'I couldn\'t disable the patreon features.', {}, true );
 					return eacherror;
 				}
-				db.run( 'UPDATE discord SET lang = ?, inline = ?, prefix = ? WHERE guild = ?', [eachrow.lang, eachrow.inline, process.env.prefix, eachrow.guild], function (uperror) {
+				db.run( 'UPDATE discord SET lang = ?, inline = ?, prefix = ?, patreon = NULL WHERE guild = ?', [eachrow.lang, eachrow.inline, process.env.prefix, eachrow.guild], function (uperror) {
 					if ( uperror ) {
 						console.log( '- Error while updating the guild: ' + uperror );
 						msg.replyMsg( 'I couldn\'t disable the patreon features for `' + eachrow.guild + '`.', {}, true );
@@ -171,7 +172,7 @@ function cmd_patreon(lang, msg, args, line, wiki) {
 					console.log( '- Error while getting the verifications: ' + eacherror );
 					return dberror;
 				}
-				var ids = eachrow.configids.split(',').slice(10).map( row => row.configid );
+				var ids = eachrow.configids.split(',').slice(verificationLimit.default);
 				if ( ids.length ) db.run( 'DELETE FROM verification WHERE guild = ? AND configid IN (' + ids.map( configid => '?' ).join(', ') + ')', [eachrow.guild, ...ids], function (uperror) {
 					if ( uperror ) {
 						console.log( '- Error while deleting the verifications: ' + uperror );

+ 2 - 2
cmds/settings.js

@@ -339,7 +339,7 @@ function input_to_wiki(input) {
 	if ( input.startsWith( 'https://' ) ) {
 		let project = wikiProjects.find( project => input.split('/')[2].endsWith( project.name ) );
 		if ( project ) {
-			regex = input.match( new RegExp( project.regex ) );
+			regex = input.match( new RegExp( project.regex + `(?:${project.articlePath}|${project.scriptPath}|/?$)` ) );
 			if ( regex ) return 'https://' + regex[1] + project.scriptPath;
 		}
 		let wiki = input.replace( /\/(?:api|index)\.php(?:|\?.*)$/, '/' );
@@ -348,7 +348,7 @@ function input_to_wiki(input) {
 	}
 	let project = wikiProjects.find( project => input.split('/')[0].endsWith( project.name ) );
 	if ( project ) {
-		regex = input.match( new RegExp( project.regex ) );
+		regex = input.match( new RegExp( project.regex + `(?:${project.articlePath}|${project.scriptPath}|/?$)` ) );
 		if ( regex ) return 'https://' + regex[1] + project.scriptPath;
 	}
 	if ( allSites.some( site => site.wiki_domain === input + '.gamepedia.com' ) ) {

+ 2 - 1
cmds/verification.js

@@ -1,3 +1,4 @@
+const {limit: {verification: verificationLimit}} = require('../util/default.json');
 var db = require('../util/database.js');
 
 function cmd_verification(lang, msg, args, line, wiki) {
@@ -20,7 +21,7 @@ function cmd_verification(lang, msg, args, line, wiki) {
 		
 		var prefix = ( patreons[msg.guild.id] || process.env.prefix );
 		if ( args[0] && args[0].toLowerCase() === 'add' ) {
-			var limit = ( msg.guild.id in patreons ? 15 : 10 );
+			var limit = verificationLimit[( msg.guild.id in patreons ? 'patreon' : 'default' )];
 			if ( rows.length >= limit ) return msg.replyMsg( lang.get('verification.max_entries'), {}, true );
 			var roles = args.slice(1).join(' ').split('|').map( role => role.replace( /^\s*<?\s*(.*?)\s*>?\s*$/, '$1' ) ).filter( role => role.length );
 			if ( !roles.length ) return msg.replyMsg( lang.get('verification.no_role') + '\n`' + prefix + 'verification add ' + lang.get('verification.new_role') + '`', {}, true );

+ 7 - 3
cmds/wiki/fandom.js

@@ -1,6 +1,6 @@
 const htmlparser = require('htmlparser2');
 const {MessageEmbed} = require('discord.js');
-const {wikiProjects} = require('../../util/default.json');
+const {limit: {interwiki: interwikiLimit}, wikiProjects} = require('../../util/default.json');
 
 const fs = require('fs');
 var fn = {
@@ -36,6 +36,10 @@ function fandom_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '',
 	
 	if ( aliasInvoke === 'random' && !args.join('') && !querystring && !fragment ) fn.random(lang, msg, wiki, reaction, spoiler);
 	else if ( aliasInvoke === 'overview' && !args.join('') && !querystring && !fragment ) fn.overview(lang, msg, wiki, reaction, spoiler);
+	else if ( aliasInvoke === 'test' && !args.join('') && !querystring && !fragment ) {
+		this.test(lang, msg, args, '', wiki);
+		if ( reaction ) reaction.removeEmoji();
+	}
 	else if ( aliasInvoke === 'page' ) {
 		msg.sendChannel( spoiler + '<' + wiki.toLink(args.join('_'), querystring.toTitle(), fragment) + '>' + spoiler );
 		if ( reaction ) reaction.removeEmoji();
@@ -388,7 +392,7 @@ function fandom_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '',
 						return;
 					}
 					interwiki = body.query.interwiki[0].url;
-					var maxselfcall = ( msg.channel.type === 'text' && msg.guild.id in patreons ? 10 : 5 );
+					var maxselfcall = interwikiLimit[( msg?.guild?.id in patreons ? 'patreon' : 'default' )];
 					if ( selfcall < maxselfcall && /^(?:https?:)?\/\//.test(interwiki) ) {
 						selfcall++;
 						var regex = interwiki.match( /^(?:https?:)?\/\/(([a-z\d-]{1,50})\.(?:fandom\.com|wikia\.org)(?:(?!\/wiki\/)\/([a-z-]{2,12}))?)(?:\/wiki\/|\/?$)/ );
@@ -405,7 +409,7 @@ function fandom_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '',
 						}
 						let project = wikiProjects.find( project => interwiki.split('/')[2].endsWith( project.name ) );
 						if ( project ) {
-							regex = interwiki.match( new RegExp( '^(?:https?:)?\\/\\/' + project.regex ) );
+							regex = interwiki.match( new RegExp( '^(?:https?:)?//' + project.regex + `(?:${project.articlePath}|/?$)` ) );
 							if ( regex ) {
 								let iwtitle = decodeURIComponent( interwiki.replace( regex[0], '' ) ).replace( /\_/g, ' ' );
 								this.gamepedia(lang, msg, iwtitle, 'https://' + regex[1] + project.scriptPath, cmd + body.query.interwiki[0].iw + ':', reaction, spoiler, querystring, fragment, interwiki, selfcall);

+ 7 - 3
cmds/wiki/gamepedia.js

@@ -1,7 +1,7 @@
 const htmlparser = require('htmlparser2');
 const {MessageEmbed} = require('discord.js');
 const extract_desc = require('../../util/extract_desc.js');
-const {wikiProjects} = require('../../util/default.json');
+const {limit: {interwiki: interwikiLimit}, wikiProjects} = require('../../util/default.json');
 
 const fs = require('fs');
 var fn = {
@@ -51,6 +51,10 @@ function gamepedia_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '
 	}
 	else if ( aliasInvoke === 'random' && !args.join('') && !querystring && !fragment ) fn.random(lang, msg, wiki, reaction, spoiler);
 	else if ( aliasInvoke === 'overview' && !args.join('') && !querystring && !fragment ) fn.overview(lang, msg, wiki, reaction, spoiler);
+	else if ( aliasInvoke === 'test' && !args.join('') && !querystring && !fragment ) {
+		this.test(lang, msg, args, '', wiki);
+		if ( reaction ) reaction.removeEmoji();
+	}
 	else if ( aliasInvoke === 'page' ) {
 		msg.sendChannel( spoiler + '<' + wiki.toLink(args.join('_'), querystring.toTitle(), fragment) + '>' + spoiler );
 		if ( reaction ) reaction.removeEmoji();
@@ -281,7 +285,7 @@ function gamepedia_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '
 						return;
 					}
 					interwiki = body.query.interwiki[0].url;
-					var maxselfcall = ( msg.channel.type === 'text' && msg.guild.id in patreons ? 10 : 5 );
+					var maxselfcall = interwikiLimit[( msg?.guild?.id in patreons ? 'patreon' : 'default' )];
 					if ( selfcall < maxselfcall && /^(?:https?:)?\/\//.test(interwiki) ) {
 						selfcall++;
 						var regex = interwiki.match( /^(?:https?:)?\/\/([a-z\d-]{1,50})\.gamepedia\.com(?:\/|$)/ );
@@ -298,7 +302,7 @@ function gamepedia_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '
 						}
 						let project = wikiProjects.find( project => interwiki.split('/')[2].endsWith( project.name ) );
 						if ( project ) {
-							regex = interwiki.match( new RegExp( '^(?:https?:)?\\/\\/' + project.regex ) );
+							regex = interwiki.match( new RegExp( '^(?:https?:)?//' + project.regex + `(?:${project.articlePath}|/?$)` ) );
 							if ( regex ) {
 								let iwtitle = decodeURIComponent( interwiki.replace( regex[0], '' ) ).replace( /\_/g, ' ' );
 								this.gamepedia(lang, msg, iwtitle, 'https://' + regex[1] + project.scriptPath, cmd + body.query.interwiki[0].iw + ':', reaction, spoiler, querystring, fragment, interwiki, selfcall);

+ 2 - 2
functions/discussion.js

@@ -1,7 +1,9 @@
 const htmlparser = require('htmlparser2');
 const {MessageEmbed} = require('discord.js');
+const {limit: {discussion: discussionLimit}} = require('../util/default.json');
 
 function fandom_discussion(lang, msg, wiki, title, query, reaction, spoiler) {
+	var limit = discussionLimit[( msg?.guild?.id in patreons ? 'patreon' : 'default' )];
 	if ( !title ) {
 		var pagelink = wiki + 'f';
 		var embed = new MessageEmbed().setAuthor( query.general.sitename ).setTitle( lang.get('discussion.main') ).setURL( pagelink );
@@ -64,7 +66,6 @@ function fandom_discussion(lang, msg, wiki, title, query, reaction, spoiler) {
 	}
 	else if ( title.split(' ')[0].toLowerCase() === 'post' || title.split(' ')[0].toLowerCase() === lang.get('discussion.post') ) {
 		title = title.split(' ').slice(1).join(' ');
-		var limit = ( msg.channel.type === 'text' && msg.guild.id in patreons ? '100' : '50' );
 		got.get( 'https://services.fandom.com/discussion/' + query.wikidesc.id + '/posts?limit=' + limit + '&format=json', {
 			headers: {
 				Accept: 'application/hal+json'
@@ -165,7 +166,6 @@ function fandom_discussion(lang, msg, wiki, title, query, reaction, spoiler) {
 		} );
 	}
 	else {
-		var limit = ( msg.channel.type === 'text' && msg.guild.id in patreons ? '100' : '50' );
 		got.get( 'https://services.fandom.com/discussion/' + query.wikidesc.id + '/threads?sortKey=trending&limit=' + limit + '&format=json', {
 			headers: {
 				Accept: 'application/hal+json'

+ 16 - 0
privacy.md

@@ -0,0 +1,16 @@
+# Privacy Policy
+This privacy policy only refers to the Discord bots `Wiki-Bot#2998` (ID:&nbsp;`461189216198590464`) and `Wiki-Bot (Test)#4262` (ID:&nbsp;`432468082175246351`).
+
+## Private data
+The bot does not collect, save or share any private data.
+
+## Other data
+The bot needs to collect and save some data in order to function properly:
+* **Settings**: Modified guild settings are saved as long as the bot is a member of that guild and deleted once the bot leaves the guild.
+* **Supporters**: The bot maintains a list of translators and [Patreon supporters](https://www.patreon.com/WikiBot) to provide some extra functionality for them.
+* **Commands**: Commands are logged together with the guild id or user id for up to 24 hours for debugging purposes.
+
+The bot does not share any data with third parties.
+
+## Contact
+`MarkusRost#8278` on the ["Help with Wiki-Bot" Discord](https://discord.gg/v77RTk5).

+ 16 - 9
util/database.js

@@ -33,7 +33,7 @@ function getSettings(trysettings = 1) {
 					db.run( 'CREATE INDEX idx_patreons_patreon ON patreons(patreon)', [], function (idxerror) {
 						if ( idxerror ) {
 							console.log( '- ' + shardId + ': Error while creating the patreons index: ' + idxerror );
-							return error;
+							return idxerror;
 						}
 						console.log( '- ' + shardId + ': Created the patreons index.' );
 					} );
@@ -44,34 +44,41 @@ function getSettings(trysettings = 1) {
 						return error;
 					}
 					console.log( '- Created the discord table.' );
-					db.run( 'CREATE TRIGGER unique_discord_guild BEFORE INSERT ON discord WHEN NEW.channel IS NULL BEGIN SELECT CASE WHEN (SELECT 1 FROM discord WHERE guild = NEW.guild AND channel IS NULL) IS NOT NULL THEN RAISE(ABORT, "UNIQUE constraint failed: discord.guild, discord.channel") END; END;', [], function (idxerror) {
-						if ( idxerror ) {
-							console.log( '- ' + shardId + ': Error while creating the discord guild trigger: ' + idxerror );
-							return error;
+					db.run( 'CREATE TRIGGER unique_discord_guild BEFORE INSERT ON discord WHEN NEW.channel IS NULL BEGIN SELECT CASE WHEN (SELECT 1 FROM discord WHERE guild = NEW.guild AND channel IS NULL) IS NOT NULL THEN RAISE(ABORT, "UNIQUE constraint failed: discord.guild, discord.channel") END; END;', [], function (tgerror) {
+						if ( tgerror ) {
+							console.log( '- ' + shardId + ': Error while creating the discord guild trigger: ' + tgerror );
+							return tgerror;
 						}
 						console.log( '- ' + shardId + ': Created the discord guild trigger.' );
 					} );
 					db.run( 'CREATE INDEX idx_discord_patreon ON discord(patreon) WHERE patreon IS NOT NULL', [], function (idxerror) {
 						if ( idxerror ) {
 							console.log( '- ' + shardId + ': Error while creating the discord patreon index: ' + idxerror );
-							return error;
+							return idxerror;
 						}
 						console.log( '- ' + shardId + ': Created the discord patreon index.' );
 					} );
 					db.run( 'CREATE INDEX idx_discord_voice ON discord(voice) WHERE voice IS NOT NULL', [], function (idxerror) {
 						if ( idxerror ) {
 							console.log( '- ' + shardId + ': Error while creating the discord voice index: ' + idxerror );
-							return error;
+							return idxerror;
 						}
 						console.log( '- ' + shardId + ': Created the discord voice index.' );
 					} );
 					db.run( 'CREATE INDEX idx_discord_channel ON discord(guild, channel DESC)', [], function (idxerror) {
 						if ( idxerror ) {
 							console.log( '- ' + shardId + ': Error while creating the discord channel index: ' + idxerror );
-							return error;
+							return idxerror;
 						}
 						console.log( '- ' + shardId + ': Created the discord channel index.' );
 					} );
+					db.run( 'PRAGMA foreign_keys = ON;', [], function (fkerror) {
+						if ( fkerror ) {
+							console.log( '- ' + shardId + ': Error while enabling the foreign key constraint: ' + fkerror );
+							return fkerror;
+						}
+						console.log( '- ' + shardId + ': Enabled the foreign key constraint.' );
+					} );
 					if ( trysettings < 10 ) {
 						trysettings++;
 						getSettings(trysettings);
@@ -86,7 +93,7 @@ function getSettings(trysettings = 1) {
 					db.run( 'CREATE INDEX idx_verification_config ON verification(guild, configid ASC, channel)', [], function (idxerror) {
 						if ( idxerror ) {
 							console.log( '- ' + shardId + ': Error while creating the verification index: ' + idxerror );
-							return error;
+							return idxerror;
 						}
 						console.log( '- ' + shardId + ': Created the verification index.' );
 					} );

+ 34 - 22
util/default.json

@@ -1,5 +1,23 @@
 {
 	"defaultPermissions": 403033152,
+	"limit": {
+		"command": {
+			"default": 10,
+			"patreon": 15
+		},
+		"interwiki": {
+			"default": 5,
+			"patreon": 10
+		},
+		"discussion": {
+			"default": 50,
+			"patreon": 100
+		},
+		"verification": {
+			"default": 10,
+			"patreon": 15
+		}
+	},
 	"defaultSettings": {
 		"lang": "en",
 		"wiki": "https://community.fandom.com/"
@@ -67,105 +85,99 @@
 	"wikiProjects": [
 		{
 			"name": "wikipedia.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikipedia\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikipedia\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "mediawiki.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?mediawiki\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?mediawiki\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "wikimedia.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikimedia\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikimedia\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "wiktionary.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?wiktionary\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?wiktionary\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "wikibooks.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikibooks\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikibooks\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "wikisource.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikisource\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikisource\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "wikidata.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikidata\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikidata\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "wikiversity.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikiversity\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikiversity\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "wikiquote.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikiquote\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikiquote\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "wikinews.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikinews\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikinews\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "wikivoyage.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikivoyage\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)?wikivoyage\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "miraheze.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)miraheze\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)miraheze\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "metapedia.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)metapedia\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)metapedia\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/m/"
 		},
 		{
 			"name": "paradoxwikis.com",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)paradoxwikis\\.com)(?:\\/|$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)paradoxwikis\\.com)",
 			"articlePath": "/",
 			"scriptPath": "/"
 		},
 		{
 			"name": "brickimedia.org",
-			"regex": "((?:[a-z\\d-]{1,50}\\.)brickimedia\\.org)(?:\\/wiki\\/|\\/?$)",
+			"regex": "((?:[a-z\\d-]{1,50}\\.)brickimedia\\.org)",
 			"articlePath": "/wiki/",
 			"scriptPath": "/w/"
 		},
 		{
 			"name": "runescape.wiki",
-			"regex": "((?:(?:classic|oldschool|pt|www)\\.)?runescape\\.wiki)(?:\\/w\\/|\\/?$)",
+			"regex": "((?:(?:classic|oldschool|pt|www)\\.)?runescape\\.wiki)",
 			"articlePath": "/w/",
 			"scriptPath": "/"
-		},
-		{
-			"name": "shoutwiki.com",
-			"regex": "DOES NOT SUPPORT HTTPS – ((?:[a-z\\d-]{1,50}\\.)?shoutwiki\\.com)(?:\\/wiki\\/|\\/?$)",
-			"articlePath": "/wiki/",
-			"scriptPath": "/w/"
 		}
 	]
 }

+ 2 - 2
util/newMessage.js

@@ -1,5 +1,5 @@
 const {Util} = require('discord.js');
-const {defaultSettings, wikiProjects} = require('./default.json');
+const {limit: {command: commandLimit}, defaultSettings, wikiProjects} = require('./default.json');
 const check_wiki = {
 	fandom: require('../cmds/wiki/fandom.js'),
 	gamepedia: require('../cmds/wiki/gamepedia.js')
@@ -37,7 +37,7 @@ function newMessage(msg, lang, wiki = defaultSettings.wiki, prefix = process.env
 		}
 	}
 	var count = 0;
-	var maxcount = ( channel.type === 'text' && msg.guild.id in patreons ? 15 : 10 );
+	var maxcount = commandLimit[( msg?.guild?.id in patreons ? 'patreon' : 'default' )];
 	cleanCont.replace( /\u200b/g, '' ).split('\n').forEach( line => {
 		if ( !line.hasPrefix(prefix) || count > maxcount ) return;
 		count++;