Explorar o código

reduce embed size, fix big infoboxes

Markus-Rost %!s(int64=4) %!d(string=hai) anos
pai
achega
2d3e746d94

+ 7 - 7
cmds/verify.js

@@ -139,7 +139,7 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 						return Promise.reject();
 					}
 					queryuser.editcount = ucbody.userData.localEdits;
-					if ( ucbody.userData.discordHandle ) discordname = ucbody.userData.discordHandle.escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
+					if ( ucbody.userData.discordHandle ) discordname = ucbody.userData.discordHandle.escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/u, '$1#$2' );
 					
 					if ( wiki.isGamepedia() ) return got.get( wiki + 'api.php?action=profile&do=getPublicProfile&user_name=' + encodeURIComponent( username ) + '&format=json&cache=' + Date.now() ).then( presponse => {
 						var pbody = presponse.body;
@@ -147,7 +147,7 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 							console.log( '- ' + presponse.statusCode + ': Error while getting the Discord tag: ' + ( pbody?.error?.info || pbody?.errormsg ) );
 							return Promise.reject();
 						}
-						if ( pbody.profile['link-discord'] ) discordname = pbody.profile['link-discord'].escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
+						if ( pbody.profile['link-discord'] ) discordname = pbody.profile['link-discord'].escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/u, '$1#$2' );
 					}, error => {
 						console.log( '- Error while getting the Discord tag: ' + error );
 						return Promise.reject();
@@ -175,14 +175,14 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 							}
 							return;
 						}
-						if ( pbody.profile ) discordname = pbody.profile['link-discord'].escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
-						else if ( pbody.value ) discordname = pbody.value.escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
+						if ( pbody.profile ) discordname = pbody.profile['link-discord'].escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/u, '$1#$2' );
+						else if ( pbody.value ) discordname = pbody.value.escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/u, '$1#$2' );
 					}, error => {
 						console.log( '- Error while getting the Discord tag: ' + error );
 						return Promise.reject();
 					} );
 				} ).then( () => {
-					if ( discordname.length > 50 ) discordname = discordname.substring(0, 50) + '\u2026';
+					if ( discordname.length > 100 ) discordname = discordname.substring(0, 100) + '\u2026';
 					embed.addField( lang.get('verify.discord', ( msg.author.tag.escapeFormatting() === discordname ? queryuser.gender : 'unknown' )), msg.author.tag.escapeFormatting(), true ).addField( lang.get('verify.wiki', queryuser.gender), ( discordname || lang.get('verify.empty') ), true );
 					if ( msg.author.tag.escapeFormatting() !== discordname ) {
 						embed.setColor('#FFFF00').setDescription( lang.get('verify.user_failed', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender) );
@@ -295,9 +295,9 @@ function cmd_verify(lang, msg, args, line, wiki, old_username = '') {
 				
 				var discordname = '';
 				if ( revision && revision.user === username ) {
-					discordname = ( revision?.slots?.main || revision )['*'].escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
+					discordname = ( revision?.slots?.main || revision )['*'].escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/u, '$1#$2' );
 				}
-				if ( discordname.length > 50 ) discordname = discordname.substring(0, 50) + '\u2026';
+				if ( discordname.length > 100 ) discordname = discordname.substring(0, 100) + '\u2026';
 				embed.addField( lang.get('verify.discord', ( msg.author.tag.escapeFormatting() === discordname ? queryuser.gender : 'unknown' )), msg.author.tag.escapeFormatting(), true ).addField( lang.get('verify.wiki', queryuser.gender), ( discordname || lang.get('verify.empty') ), true );
 				if ( msg.author.tag.escapeFormatting() !== discordname ) {
 					embed.setColor('#FFFF00').setDescription( lang.get('verify.user_failed', msg.member.toString(), '[' + username.escapeFormatting() + '](' + pagelink + ')', queryuser.gender) );

+ 4 - 4
cmds/wiki/fandom/general.js

@@ -176,7 +176,7 @@ function fandom_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '',
 										onopentag: (tagname, attribs) => {
 											if ( tagname === 'meta' && attribs.property === 'og:description' ) {
 												var description = attribs.content.escapeFormatting();
-												if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+												if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 												embed.setDescription( description );
 											}
 											if ( tagname === 'meta' && attribs.property === 'og:image' ) {
@@ -291,7 +291,7 @@ function fandom_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '',
 											onopentag: (tagname, attribs) => {
 												if ( tagname === 'meta' && attribs.property === 'og:description' ) {
 													var description = attribs.content.escapeFormatting();
-													if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+													if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 													embed.setDescription( description );
 												}
 												if ( tagname === 'meta' && attribs.property === 'og:image' && querypage.title !== body.query.general.mainpage ) {
@@ -380,7 +380,7 @@ function fandom_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '',
 							onopentag: (tagname, attribs) => {
 								if ( tagname === 'meta' && attribs.property === 'og:description' ) {
 									var description = attribs.content.escapeFormatting();
-									if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+									if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 									embed.setDescription( description );
 								}
 								if ( tagname === 'meta' && attribs.property === 'og:image' && querypage.title !== body.query.general.mainpage ) {
@@ -475,7 +475,7 @@ function fandom_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '',
 						onopentag: (tagname, attribs) => {
 							if ( tagname === 'meta' && attribs.property === 'og:description' ) {
 								var description = attribs.content.escapeFormatting();
-								if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+								if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 								embed.setDescription( description );
 							}
 						}

+ 1 - 1
cmds/wiki/fandom/random.js

@@ -49,7 +49,7 @@ function fandom_random(lang, msg, wiki, reaction, spoiler) {
 						onopentag: (tagname, attribs) => {
 							if ( tagname === 'meta' && attribs.property === 'og:description' ) {
 								var description = attribs.content.escapeFormatting();
-								if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+								if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 								embed.setDescription( description );
 							}
 							if ( tagname === 'meta' && attribs.property === 'og:image' && querypage.title !== body.query.general.mainpage ) {

+ 5 - 5
cmds/wiki/fandom/user.js

@@ -45,7 +45,7 @@ function fandom_user(lang, msg, namespace, username, wiki, querystring, fragment
 									onopentag: (tagname, attribs) => {
 										if ( tagname === 'meta' && attribs.property === 'og:description' ) {
 											var description = attribs.content.escapeFormatting();
-											if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+											if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 											embed.setDescription( description );
 										}
 										if ( tagname === 'meta' && attribs.property === 'og:image' ) {
@@ -205,7 +205,7 @@ function fandom_user(lang, msg, namespace, username, wiki, querystring, fragment
 									onopentag: (tagname, attribs) => {
 										if ( tagname === 'meta' && attribs.property === 'og:description' ) {
 											var description = attribs.content.escapeFormatting();
-											if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+											if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 											embed.setDescription( description );
 										}
 										if ( tagname === 'meta' && attribs.property === 'og:image' ) {
@@ -304,8 +304,8 @@ function fandom_user(lang, msg, namespace, username, wiki, querystring, fragment
 							var avatarfield = profile.find( field => field.name === 'avatar' );
 							var biofield = profile.find( field => field.name === 'bio' );
 							if ( discordfield && discordfield.value ) {
-								discordfield.value = htmlToPlain( discordfield.value ).replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
-								if ( discordfield.value.length > 50 ) discordfield.value = discordfield.value.substring(0, 50) + '\u2026';
+								discordfield.value = htmlToPlain( discordfield.value ).replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/u, '$1#$2' );
+								if ( discordfield.value.length > 100 ) discordfield.value = discordfield.value.substring(0, 100) + '\u2026';
 								if ( msg.channel.isGuild() ) var discordmember = msg.guild.members.cache.find( member => {
 									return member.user.tag.escapeFormatting() === discordfield.value;
 								} );
@@ -319,7 +319,7 @@ function fandom_user(lang, msg, namespace, username, wiki, querystring, fragment
 								if ( avatarfield && avatarfield.value ) embed.setThumbnail( avatarfield.value );
 								if ( biofield && biofield.value && !embed.description ) {
 									var bio = biofield.value.escapeFormatting();
-									if ( bio.length > 2000 ) bio = bio.substring(0, 2000) + '\u2026';
+									if ( bio.length > 1000 ) bio = bio.substring(0, 1000) + '\u2026';
 									embed.setDescription( bio );
 								}
 							}

+ 3 - 3
cmds/wiki/general.js

@@ -212,7 +212,7 @@ function gamepedia_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '
 							}
 							if ( querypage.pageprops && querypage.pageprops.description ) {
 								var description = htmlToPlain( querypage.pageprops.description );
-								if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+								if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 								embed.setDescription( description );
 							}
 							if ( querypage.ns === 6 ) {
@@ -317,7 +317,7 @@ function gamepedia_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '
 				}
 				if ( querypage.pageprops && querypage.pageprops.description ) {
 					var description = htmlToPlain( querypage.pageprops.description );
-					if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+					if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 					embed.setDescription( description );
 				}
 				if ( querypage.ns === 6 ) {
@@ -436,7 +436,7 @@ function gamepedia_check_wiki(lang, msg, title, wiki, cmd, reaction, spoiler = '
 					}
 					if ( querypage.pageprops && querypage.pageprops.description ) {
 						var description = htmlToPlain( querypage.pageprops.description );
-						if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+						if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 						embed.setDescription( description );
 					}
 				}

+ 1 - 1
cmds/wiki/random.js

@@ -40,7 +40,7 @@ function gamepedia_random(lang, msg, wiki, reaction, spoiler) {
 			}
 			if ( querypage.pageprops && querypage.pageprops.description ) {
 				var description = htmlToPlain( querypage.pageprops.description );
-				if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+				if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 				embed.setDescription( description );
 			}
 			else if ( querypage.extract ) {

+ 11 - 11
cmds/wiki/user.js

@@ -51,7 +51,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 					}
 					if ( querypage.pageprops && querypage.pageprops.description ) {
 						var description = htmlToPlain( querypage.pageprops.description );
-						if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+						if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 						embed.setDescription( description );
 					}
 					if ( querypage.pageimage && querypage.original ) {
@@ -133,7 +133,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 				var embed = new MessageEmbed().setAuthor( body.query.general.sitename ).setTitle( username ).setURL( pagelink ).addField( editcount[0], '[' + editcount[1] + '](' + wiki.toLink(contribs + username, '', '', true) + ')' );
 				if ( querypage.pageprops && querypage.pageprops.description ) {
 					var description = htmlToPlain( querypage.pageprops.description );
-					if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+					if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 					embed.setDescription( description );
 				}
 				else if ( querypage.extract ) {
@@ -205,7 +205,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 				}
 				if ( querypage.pageprops && querypage.pageprops.description ) {
 					var description = htmlToPlain( querypage.pageprops.description );
-					if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+					if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 					embed.setDescription( description );
 				}
 				if ( querypage.pageimage && querypage.original ) {
@@ -338,7 +338,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 				
 				if ( querypage.pageprops && querypage.pageprops.description ) {
 					var description = htmlToPlain( querypage.pageprops.description );
-					if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+					if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 					embed.setDescription( description );
 				}
 				else if ( querypage.extract ) {
@@ -379,7 +379,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 					}
 					if ( pbody.userData.bio && !embed.description ) {
 						let bio = pbody.userData.bio.escapeFormatting();
-						if ( bio.length > 2000 ) bio = bio.substring(0, 2000) + '\u2026';
+						if ( bio.length > 1000 ) bio = bio.substring(0, 1000) + '\u2026';
 						embed.setDescription( bio );
 					}
 				}
@@ -391,8 +391,8 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 				}
 				var discord = '';
 				if ( pbody.userData.discordHandle ) {
-					discord = pbody.userData.discordHandle.escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
-					if ( discord.length > 50 ) discord = discord.substring(0, 50) + '\u2026';
+					discord = pbody.userData.discordHandle.escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/u, '$1#$2' );
+					if ( discord.length > 100 ) discord = discord.substring(0, 100) + '\u2026';
 				}
 				if ( wiki.isGamepedia() ) return got.get( wiki + 'api.php?action=profile&do=getPublicProfile&user_name=' + encodeURIComponent( username ) + '&format=json&cache=' + Date.now() ).then( cpresponse => {
 					var cpbody = cpresponse.body;
@@ -401,8 +401,8 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 						return;
 					}
 					if ( cpbody.profile['link-discord'] ) {
-						discord = cpbody.profile['link-discord'].escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
-						if ( discord.length > 50 ) discord = discord.substring(0, 50) + '\u2026';
+						discord = cpbody.profile['link-discord'].escapeFormatting().replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/u, '$1#$2' );
+						if ( discord.length > 100 ) discord = discord.substring(0, 100) + '\u2026';
 					}
 					if ( discord ) {
 						if ( msg.channel.isGuild() ) {
@@ -469,8 +469,8 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 			if ( body.query.pages ) {
 				let revision = Object.values(body.query.pages)[0]?.revisions?.[0];
 				if ( revision?.user === username ) {
-					let discord = ( revision?.slots?.main || revision )['*'].replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
-					if ( discord.length > 50 ) discord = discord.substring(0, 50) + '\u2026';
+					let discord = ( revision?.slots?.main || revision )['*'].replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/u, '$1#$2' );
+					if ( discord.length > 100 ) discord = discord.substring(0, 100) + '\u2026';
 					if ( msg.channel.isGuild() ) var discordmember = msg.guild.members.cache.find( member => {
 						return member.user.tag === discord;
 					} );

+ 1 - 1
functions/discussion.js

@@ -29,7 +29,7 @@ function fandom_discussion(lang, msg, wiki, title, query, reaction, spoiler) {
 					onopentag: (tagname, attribs) => {
 						if ( tagname === 'meta' && attribs.property === 'og:description' ) {
 							var description = attribs.content.escapeFormatting();
-							if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+							if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 							embed.setDescription( description );
 						}
 						if ( tagname === 'meta' && attribs.property === 'og:image' ) {

+ 26 - 3
functions/parse_page.js

@@ -1,4 +1,5 @@
 const cheerio = require('cheerio');
+const {htmlToPlain} = require('../util/functions.js');
 
 const infoboxList = [
 	'.infobox',
@@ -40,7 +41,9 @@ const keepMainPageTag = [
  * @param {String} thumbnail - The default thumbnail for the wiki.
  */
 function parse_page(msg, title, embed, wiki, thumbnail) {
-	if ( !msg || ( embed.description && embed.thumbnail?.url !== thumbnail ) ) return;
+	if ( !msg || ( embed.description && embed.thumbnail?.url !== thumbnail && !embed.brokenInfobox ) ) {
+		return;
+	}
 	got.get( wiki + 'api.php?action=parse&prop=text|images|parsewarnings&section=0&disablelimitreport=true&disableeditsection=true&disabletoc=true&page=' + encodeURIComponent( title ) + '&format=json' ).then( response => {
 		if ( response?.body?.parse?.parsewarnings?.length ) log_warn(response.body.parse.parsewarnings);
 		if ( response.statusCode !== 200 || !response?.body?.parse?.text ) {
@@ -49,6 +52,25 @@ function parse_page(msg, title, embed, wiki, thumbnail) {
 		}
 		var change = false;
 		var $ = cheerio.load(response.body.parse.text['*'].replace( /<br\/?>/g, '\n' ));
+		if ( embed.brokenInfobox && $('aside.portable-infobox').length ) {
+			var infobox = $('aside.portable-infobox');
+			embed.fields.forEach( field => {
+				if ( embed.length > 5500 ) return;
+				if ( /^`.+`$/.test(field.name) ) {
+					let label = infobox.find(field.name.replace( /^`(.+)`$/, '[data-source="$1"] .pi-data-label, .pi-data-label[data-source="$1"]' )).html();
+					label = htmlToPlain(label).trim();
+					if ( label.length > 50 ) label = label.substring(0, 50) + '\u2026';
+					if ( label ) field.name = label;
+				}
+				if ( /^`.+`$/.test(field.value) ) {
+					let value = infobox.find(field.value.replace( /^`(.+)`$/, '[data-source="$1"] .pi-data-value, .pi-data-value[data-source="$1"]' )).html();
+					value = htmlToPlain(value).trim();
+					if ( value.length > 250 ) value = value.substring(0, 250) + '\u2026';
+					if ( value ) field.value = value;
+				}
+			} );
+			change = true;
+		}
 		if ( embed.thumbnail?.url === thumbnail ) {
 			var image = response.body.parse.images.find( pageimage => ( /\.(?:png|jpg|jpeg|gif)$/.test(pageimage.toLowerCase()) && pageimage.toLowerCase().includes( title.toLowerCase().replace( / /g, '_' ) ) ) );
 			if ( !image ) {
@@ -70,13 +92,14 @@ function parse_page(msg, title, embed, wiki, thumbnail) {
 				change = true;
 			}
 		}
-		if ( !embed.description ) {
+		if ( !embed.description && embed.length < 5000 ) {
 			$('h1, h2, h3, h4, h5, h6').nextAll().remove();
 			$('h1, h2, h3, h4, h5, h6').remove();
+			$(infoboxList.join(', ')).remove();
 			$(removeClasses.join(', '), $('.mw-parser-output')).not(keepMainPageTag.join(', ')).remove();
 			var description = $.text().trim().replace( /\n{3,}/g, '\n\n' ).escapeFormatting();
 			if ( description ) {
-				if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+				if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 				embed.setDescription( description );
 				change = true;
 			}

+ 1 - 1
functions/special_page.js

@@ -139,7 +139,7 @@ function special_page(lang, msg, title, specialpage, embed, wiki, reaction, spoi
 		else {
 			if ( body.query.allmessages[0]['*'] ) {
 				var description = toPlaintext(body.query.allmessages[0]['*'], true);
-				if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
+				if ( description.length > 1000 ) description = description.substring(0, 1000) + '\u2026';
 				embed.setDescription( description );
 			}
 			if ( msg.channel.isGuild() && msg.guild.id in patreons && specialpage in querypages ) {

+ 1 - 1
util/extract_desc.js

@@ -7,7 +7,7 @@
 function extract_desc(text = '', fragment = '') {
 	var sectionIndex = text.indexOf('\ufffd\ufffd');
 	var extract = ( sectionIndex !== -1 ? text.substring(0, sectionIndex) : text ).trim().escapeFormatting();
-	if ( extract.length > 2000 ) extract = extract.substring(0, 2000) + '\u2026';
+	if ( extract.length > 1000 ) extract = extract.substring(0, 1000) + '\u2026';
 	var section = null;
 	var regex = /\ufffd{2}(\d)\ufffd{2}([^\n]+)/g;
 	var sectionHeader = '';

+ 30 - 4
util/functions.js

@@ -15,12 +15,22 @@ const got = require('got').extend( {
  * @param {String} [thumbnail] - The default thumbnail for the wiki.
  */
 function parse_infobox(infobox, embed, thumbnail) {
-	if ( embed.fields.length >= 25 ) return;
+	if ( embed.fields.length >= 25 || embed.length > 5500 ) return;
 	switch ( infobox.type ) {
 		case 'data':
-			var {label = '', value = ''} = infobox.data;
+			var {label = '', value = '', source = ''} = infobox.data;
 			label = htmlToPlain(label).trim();
 			value = htmlToPlain(value).trim();
+			if ( label.includes( '*UNKNOWN LINK*' ) ) {
+				label = '`' + source + '`';
+				embed.brokenInfobox = true;
+			}
+			if ( value.includes( '*UNKNOWN LINK*' ) ) {
+				value = '`' + source + '`';
+				embed.brokenInfobox = true;
+			}
+			if ( label.length > 50 ) label = label.substring(0, 50) + '\u2026';
+			if ( value.length > 250 ) value = value.substring(0, 250) + '\u2026';
 			if ( label && value ) embed.addField( label, value, true );
 			break;
 		case 'group':
@@ -31,6 +41,7 @@ function parse_infobox(infobox, embed, thumbnail) {
 		case 'header':
 			var {value = ''} = infobox.data;
 			value = htmlToPlain(value).trim();
+			if ( value.length > 100 ) value = value.substring(0, 100) + '\u2026';
 			if ( value ) embed.addField( '\u200b', '__**' + value + '**__', false );
 			break;
 		case 'image':
@@ -112,16 +123,31 @@ function toPlaintext(text = '', fullWikitext = false) {
 function htmlToPlain(html) {
 	var text = '';
 	var reference = false;
+	var listlevel = -1;
 	var parser = new htmlparser.Parser( {
 		onopentag: (tagname, attribs) => {
 			if ( tagname === 'sup' && attribs.class === 'reference' ) reference = true;
-			if ( tagname === 'br' ) text += '\n';
+			if ( tagname === 'br' ) {
+				text += '\n';
+				if ( listlevel > -1 ) text += '\u200b '.repeat(4*listlevel+3);
+			}
+			if ( tagname === 'ul' ) listlevel++;
+			if ( tagname === 'li' ) text += '\n' + '\u200b '.repeat(4*listlevel) + '• ';
 		},
 		ontext: (htmltext) => {
-			if ( !reference ) text += escapeFormatting(htmltext);
+			if ( !reference ) {
+				if ( listlevel > -1 ) {
+					htmltext = htmltext.replace( /\n/g, '\n' + '\u200b '.repeat(4*listlevel+3) );
+				}
+				text += escapeFormatting(htmltext);
+			}
 		},
 		onclosetag: (tagname) => {
 			if ( tagname === 'sup' ) reference = false;
+			if ( tagname === 'ul' ) listlevel--;
+		},
+		oncomment: (commenttext) => {
+			if ( /^LINK'" \d+:\d+$/.test(commenttext) ) text += '*UNKNOWN LINK*';
 		}
 	} );
 	parser.write( html );