Browse Source

minor improvements

Markus-Rost 5 years ago
parent
commit
64a0bccc2a
12 changed files with 125 additions and 53 deletions
  1. 1 0
      .gitignore
  2. 2 2
      README.md
  3. 1 0
      i18n/de.json
  4. 1 0
      i18n/en.json
  5. 1 0
      i18n/fr.json
  6. 1 0
      i18n/nl.json
  7. 1 0
      i18n/pl.json
  8. 1 0
      i18n/pt.json
  9. 1 0
      i18n/ru.json
  10. 1 0
      i18n/tr.json
  11. 16 15
      i18n/zh.json
  12. 98 36
      main.js

+ 1 - 0
.gitignore

@@ -1,5 +1,6 @@
 node_modules/
 package-lock.json
+*.code-workspace
 *.env
 *.db
 *.bat

+ 2 - 2
README.md

@@ -1,12 +1,12 @@
 # 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://discordapp.com/) with the purpose to easily link to [Gamepedia](https://www.gamepedia.com/) and [Fandom](https://www.fandom.com/) wikis.
+**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.
 
 **Wiki-Bot is not affiliated with Fandom and is an unofficial tool!**
 
-[Use this link to invite **Wiki-Bot** to your Discord server.](https://discordapp.com/oauth2/authorize?client_id=461189216198590464&permissions=268815424&scope=bot)
+[Use this link to invite **Wiki-Bot** to your Discord server.](https://discord.com/oauth2/authorize?client_id=461189216198590464&permissions=268815424&scope=bot)
 
 Support server: [https://discord.gg/v77RTk5](https://discord.gg/v77RTk5)
 

+ 1 - 0
i18n/de.json

@@ -150,6 +150,7 @@
 			"wikisedited": "Wikis bearbeitet:",
 			"group": "Gruppe:",
 			"discord": "Discord:",
+			"favwiki": "Lieblingswiki:",
 			"loading": "Lade globale Statistiken…"
 		},
 		"block": {

+ 1 - 0
i18n/en.json

@@ -145,6 +145,7 @@
 			"wikisedited": "Wikis edited:",
 			"group": "Group:",
 			"discord": "Discord:",
+			"favwiki": "Favorite wiki:",
 			"loading": "Loading global statistics…"
 		},
 		"block": {

+ 1 - 0
i18n/fr.json

@@ -147,6 +147,7 @@
 			"wikisedited": "Wikis modifiés :",
 			"group": "Groupe :",
 			"discord": "Discord :",
+			"favwiki": "Wiki favori:",
 			"loading": "Chargement des statistiques globales…"
 		},
 		"block": {

+ 1 - 0
i18n/nl.json

@@ -149,6 +149,7 @@
 			"wikisedited": "Wikis bewerkt:",
 			"group": "Groep:",
 			"discord": "Discord:",
+			"favwiki": "Favorite wiki:",
 			"loading": "Globale statistieken laden…"
 		},
 		"block": {

+ 1 - 0
i18n/pl.json

@@ -148,6 +148,7 @@
 			"wikisedited": "Edytowanych wiki",
 			"group": "Grupa:",
 			"discord": "Discord:",
+			"favwiki": "Ulubiona wiki:",
 			"loading": "Ładowanie globalnych statystyk…"
 		},
 		"block": {

+ 1 - 0
i18n/pt.json

@@ -150,6 +150,7 @@
 			"wikisedited": "Wikis editadas:",
 			"group": "Grupo:",
 			"discord": "Discord:",
+			"favwiki": "Wiki Favorita:",
 			"loading": "Carregando estatísticas globais…"
 		},
 		"block": {

+ 1 - 0
i18n/ru.json

@@ -147,6 +147,7 @@
 			"wikisedited": "Отредактировано вики:",
 			"group": "Группа:",
 			"discord": "Дискорд:",
+			"favwiki": "Домашняя вики:",
 			"loading": "Загрузка глобальной статистики…"
 		},
 		"block": {

+ 1 - 0
i18n/tr.json

@@ -149,6 +149,7 @@
 			"wikisedited": "Düzenlenen wikiler:",
 			"group": "Grup:",
 			"discord": "Discord:",
+			"favwiki": "Favorite wiki:",
 			"loading": "Global istatistikler yükleniyor…"
 		},
 		"block": {

+ 16 - 15
i18n/zh.json

@@ -73,7 +73,7 @@
 		"disabled": "您禁用了给予每个在这个语音频道的用户一个特定的身份组的功能。",
 		"name": "语音频道名",
 		"channel": "语音频道",
-		"join": "%1$s 加入了语音频道“%2$s\”。",
+		"join": "%1$s 加入了语音频道“%2$s”。",
 		"left": "%1$s 离开了语音频道“%2$s”。"
 	},
 	"overview": {
@@ -140,13 +140,14 @@
 			["user", "用户"]
 		],
 		"info": {
-			"gender": "性别:",
-			"registration": "注册时间:",
-			"editcount": "编辑数:",
+			"gender": "性别",
+			"registration": "注册时间",
+			"editcount": "编辑数",
 			"globaleditcount": "全域编辑数:",
 			"wikisedited": "编辑过的wiki:",
-			"group": "用户组:",
+			"group": "用户组",
 			"discord": "Discord:",
+			"favwiki": "最喜爱的wiki:",
 			"loading": "正在加载全域数据…"
 		},
 		"block": {
@@ -169,14 +170,14 @@
 		"nocomment": "*未提供描述*",
 		"hidden": "*隐藏*",
 		"info": {
-			"editor": "编辑者:",
-			"timestamp": "时间:",
-			"size": "差异:",
+			"editor": "编辑者",
+			"timestamp": "时间",
+			"size": "差异",
 			"bytes": "%s Bytes",
-			"comment": "摘要:",
-			"tags": "标签:",
-			"removed": "删除:",
-			"added": "添加:",
+			"comment": "摘要",
+			"tags": "标签",
+			"removed": "删除",
+			"added": "添加",
 			"more": "更多",
 			"whitespace": "仅有空白"
 		}
@@ -187,7 +188,7 @@
 		"infopage": "结果不正确?用%s来指定连接",
 		"infosearch": "结果不正确?用%1$s来指定链接或%2$s列出所有结果",
 		"category": {
-			"content": "分类下的内容:",
+			"content": "分类下的内容",
 			"empty": "*空白分类*",
 			"pages": {
 				"default": "%s 个页面"
@@ -270,8 +271,8 @@
 			{ "cmd": "settings wiki <wiki>", "desc": "我将更改本伺服器的默认wiki。", "hide": true, "admin": true },
 			{ "cmd": "settings channel", "desc": "我将更改本伺服器的当前频道的覆盖设置。", "hide": true, "admin": true },
 			{ "cmd": "voice", "desc": "我将尝试给予每个在这个语音频道的用户一个特定的身份组。", "admin": true, "pause": true },
-			{ "cmd": "pause @提及", "desc": "我将屏蔽少数管理指令外的全部指令", "admin": true },
-			{ "cmd": "pause @提及", "desc": "我将重新接受全部指令", "unsearchable": true, "hide": true, "pause": true },
+			{ "cmd": "pause @mention", "desc": "我将屏蔽少数管理指令外的全部指令", "admin": true },
+			{ "cmd": "pause @mention", "desc": "我将重新接受全部指令", "unsearchable": true, "hide": true, "pause": true },
 			{ "cmd": "test", "desc": "如果我被激活了,我就会回答你!否则不会。", "pause": true }
 		]
 	}

+ 98 - 36
main.js

@@ -205,7 +205,7 @@ function getVoice(trysettings = 1) {
 var allSites = [];
 function getAllSites() {
 	ready.allSites = true;
-	got.get( 'https://help.gamepedia.com/api.php?action=allsites&formatversion=2&do=getSiteStats&filter=wikis|wiki_domain,wiki_display_name,wiki_image,wiki_description,wiki_managers,official_wiki,wiki_crossover,created&format=json', {
+	got.get( 'https://help.gamepedia.com/api.php?action=allsites&formatversion=2&do=getSiteStats&filter=wikis|md5_key,wiki_domain,wiki_display_name,wiki_image,wiki_description,wiki_managers,official_wiki,wiki_crossover,created&format=json', {
 		responseType: 'json'
 	} ).then( response => {
 		var body = response.body;
@@ -719,17 +719,17 @@ function cmd_say(lang, msg, args, line, wiki) {
 	if ( msg.uploadFiles() ) imgs = msg.attachments.map( function(img) {
 		return {attachment:img.url,name:img.filename};
 	} );
-	try {
-		text = eval( '`' + text + '`' );
-	} catch ( error ) {
-		log_error(error);
+	if ( text.includes( '${' ) ) {
+		try {
+			text = eval( '`' + text + '`' );
+		} catch ( error ) {
+			log_error(error);
+		}
 	}
 	if ( text.trim() || imgs.length ) {
-		var allowedMentions = {};
-		if ( !msg.member.hasPermission(['MENTION_EVERYONE']) ) {
-			allowedMentions.parse = ['users'];
-			allowedMentions.roles = msg.guild.roles.cache.filter( role => role.mentionable ).map( role => role.id ).slice(0,100);
-		}
+		var allowedMentions = {parse:['users']};
+		if ( msg.member.hasPermission(['MENTION_EVERYONE']) ) allowedMentions.parse = ['users','roles','everyone'];
+		else allowedMentions.roles = msg.guild.roles.cache.filter( role => role.mentionable ).map( role => role.id ).slice(0,100)
 		msg.channel.send( text, {allowedMentions,files:imgs} ).then( () => msg.deleteMsg(), error => {
 			log_error(error);
 			msg.reactEmoji('error', true);
@@ -1854,7 +1854,7 @@ function gamepedia_search(lang, msg, searchterm, wiki, query, reaction, spoiler)
 		}
 		if ( searchterm.trim() ) {
 			body.query.search.forEach( result => {
-				description.push( '• [' + result.title + '](' + wiki.toLink(result.title, '', '', query.general) + ')' + ( result.sectiontitle ? ' § [' + result.sectiontitle + '](' + wiki.toLink(result.title, '', result.sectiontitle, query.general) + ')' : '' ) + ( result.redirecttitle ? ' (⤷ [' + result.redirecttitle + '](' + wiki.toLink(result.redirecttitle, '', '', query.general) + '))' : '' ) );
+				description.push( '• [' + result.title + '](' + wiki.toLink(result.title, '', '', query.general, true) + ')' + ( result.sectiontitle ? ' § [' + result.sectiontitle + '](' + wiki.toLink(result.title, '', result.sectiontitle, query.general, true) + ')' : '' ) + ( result.redirecttitle ? ' (⤷ [' + result.redirecttitle + '](' + wiki.toLink(result.redirecttitle, '', '', query.general, true) + '))' : '' ) );
 			} );
 			embed.setFooter( ( lang.search.results[body.query.searchinfo.totalhits] || lang.search.results['*' + body.query.searchinfo.totalhits % 100] || lang.search.results['*' + body.query.searchinfo.totalhits % 10]  || lang.search.results.default ).replaceSave( '%s', body.query.searchinfo.totalhits ) );
 		}
@@ -1895,7 +1895,7 @@ function fandom_search(lang, msg, searchterm, wiki, query, reaction, spoiler) {
 			return;
 		}
 		body.items.forEach( result => {
-			description.push( '• [' + result.title + '](' + wiki.toLink(result.title, '', '', query.general) + ')' );
+			description.push( '• [' + result.title + '](' + wiki.toLink(result.title, '', '', query.general, true) + ')' );
 		} );
 		embed.setFooter( ( lang.search.results[body.total] || lang.search.results['*' + body.total % 100] || lang.search.results['*' + body.total % 10]  || lang.search.results.default ).replaceSave( '%s', body.total ) );
 	}, error => {
@@ -2149,15 +2149,24 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 						if ( presponse.statusCode !== 200 || !pbody || pbody.error || pbody.errormsg || !pbody.profile ) {
 							console.log( '- ' + presponse.statusCode + ': Error while getting the user profile: ' + ( pbody && ( pbody.error && pbody.error.info || pbody.errormsg ) ) );
 						}
-						else if ( pbody.profile['link-discord'] ) {
-							if ( msg.channel.type === 'text' ) var discordmember = msg.guild.members.cache.find( member => {
-								return member.user.tag === pbody.profile['link-discord'].replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
-							} );
-							var discordname = [lang.user.info.discord,pbody.profile['link-discord'].escapeFormatting()];
-							if ( discordmember ) discordname[1] = discordmember.toString();
-							
-							if ( msg.showEmbed() ) embed.addField( discordname[0], discordname[1], true );
-							else text += '\n' + discordname.join(' ');
+						else {
+							if ( pbody.profile['link-discord'] ) {
+								if ( msg.channel.type === 'text' ) var discordmember = msg.guild.members.cache.find( member => {
+									return member.user.tag === pbody.profile['link-discord'].replace( /^\s*([^@#:]{2,32}?)\s*#(\d{4,6})\s*$/, '$1#$2' );
+								} );
+								var discordname = [lang.user.info.discord,pbody.profile['link-discord'].escapeFormatting()];
+								if ( discordmember ) discordname[1] = discordmember.toString();
+								
+								if ( msg.showEmbed() ) embed.addField( discordname[0], discordname[1], true );
+								else text += '\n' + discordname.join(' ');
+							}
+							if ( pbody.profile['favwiki'] ) {
+								var favwiki = [lang.user.info.favwiki,allSites.find( site => site.md5_key === pbody.profile['favwiki'] )];
+								if ( favwiki[1] ) {
+									if ( msg.showEmbed() ) embed.addField( favwiki[0], '[' + favwiki[1].wiki_display_name + '](<https://' + favwiki[1].wiki_domain + '/>)', true );
+									else text += '\n' + favwiki[0] + ' <https://' + favwiki[1].wiki_domain + '/>';
+								}
+							}
 						}
 					}, error => {
 						console.log( '- Error while getting the user profile: ' + error );
@@ -2191,6 +2200,7 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 							var profile = pbody._embedded.properties;
 							var discordfield = profile.find( field => field.name === 'discordHandle' );
 							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 );
 								if ( msg.channel.type === 'text' ) var discordmember = msg.guild.members.cache.find( member => {
@@ -2202,7 +2212,10 @@ function gamepedia_user(lang, msg, namespace, username, wiki, querystring, fragm
 								if ( msg.showEmbed() ) embed.addField( discordname[0], discordname[1], true );
 								else text += '\n' + discordname.join(' ');
 							}
-							if ( msg.showEmbed() && avatarfield && avatarfield.value ) embed.setThumbnail( avatarfield.value );
+							if ( msg.showEmbed() ) {
+								if ( avatarfield && avatarfield.value ) embed.setThumbnail( avatarfield.value );
+								if ( biofield && biofield.value && !embed.description ) embed.setDescription( biofield.value.escapeFormatting() );
+							}
 						}
 					}, error => {
 						console.log( '- Error while getting the user profile: ' + error );
@@ -2500,6 +2513,7 @@ function fandom_user(lang, msg, namespace, username, wiki, querystring, fragment
 							var profile = pbody._embedded.properties;
 							var discordfield = profile.find( field => field.name === 'discordHandle' );
 							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 );
 								if ( msg.channel.type === 'text' ) var discordmember = msg.guild.members.cache.find( member => {
@@ -2511,7 +2525,10 @@ function fandom_user(lang, msg, namespace, username, wiki, querystring, fragment
 								if ( msg.showEmbed() ) embed.addField( discordname[0], discordname[1], true );
 								else text += '\n' + discordname.join(' ');
 							}
-							if ( msg.showEmbed() && avatarfield && avatarfield.value ) embed.setThumbnail( avatarfield.value );
+							if ( msg.showEmbed() ) {
+								if ( avatarfield && avatarfield.value ) embed.setThumbnail( avatarfield.value );
+								if ( biofield && biofield.value && !embed.description ) embed.setDescription( biofield.value.escapeFormatting() );
+							}
 						}
 					}, error => {
 						console.log( '- Error while getting the user profile: ' + error );
@@ -2730,7 +2747,8 @@ function fandom_discussion(lang, msg, wiki, title, query, reaction, spoiler) {
 	}
 	else if ( title.split(' ')[0].toLowerCase() === 'post' || title.split(' ')[0].toLowerCase() === lang.discussion.post ) {
 		title = title.split(' ').slice(1).join(' ');
-		got.get( 'https://services.fandom.com/discussion/' + query.wikidesc.id + '/posts?limit=50&format=json', {
+		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'
 			},
@@ -2830,7 +2848,8 @@ function fandom_discussion(lang, msg, wiki, title, query, reaction, spoiler) {
 		} );
 	}
 	else {
-		got.get( 'https://services.fandom.com/discussion/' + query.wikidesc.id + '/threads?sortKey=trending&limit=50&format=json', {
+		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'
 			},
@@ -2959,7 +2978,8 @@ function fandom_discussionsend(lang, msg, wiki, discussion, embed, spoiler) {
 						}
 						else {
 							description = description.replace( /\{\@(\d+)\}/g, (match, n) => {
-								return '[__' + lang.discussion.image.escapeFormatting() + '__](' + discussion._embedded.contentImages[n].url + ')';
+								if ( n >= discussion._embedded.contentImages.length ) return '';
+								else return '[__' + lang.discussion.image.escapeFormatting() + '__](' + discussion._embedded.contentImages[n].url + ')';
 							} );
 							embed.setThumbnail( discussion._embedded.contentImages[0].url );
 						}
@@ -2969,22 +2989,36 @@ function fandom_discussionsend(lang, msg, wiki, discussion, embed, spoiler) {
 				catch ( jsonerror ) {
 					console.log( '- Error while getting the formatting: ' + jsonerror );
 					description = discussion.rawContent.escapeFormatting();
+					if ( discussion._embedded.contentImages.length ) embed.setThumbnail( discussion._embedded.contentImages[0].url );
 				}
 			}
 			else if ( discussion.renderedContent ) {
+				var current_tag = '';
 				var parser = new htmlparser.Parser( {
+					onopentag: (tagname, attribs) => {
+						if ( tagname === 'a' ) {
+							current_tag = attribs.href;
+							description += '[';
+						}
+					},
 					ontext: (htmltext) => {
 						description += htmltext.escapeFormatting();
 					},
 					onclosetag: (tagname) => {
+						if ( tagname === 'a' ) {
+							description += '](' + current_tag + ')';
+							current_tag = '';
+						}
 						if ( tagname === 'p' ) description += '\n';
 					}
 				}, {decodeEntities:true} );
 				parser.write( discussion.renderedContent );
 				parser.end();
+				if ( discussion._embedded.contentImages.length ) embed.setThumbnail( discussion._embedded.contentImages[0].url );
 			}
 			else {
 				description = discussion.rawContent.escapeFormatting();
+				if ( discussion._embedded.contentImages.length ) embed.setThumbnail( discussion._embedded.contentImages[0].url );
 			}
 	}
 	if ( description.length > 2000 ) description = description.substring(0, 2000) + '\u2026';
@@ -3984,7 +4018,7 @@ function fandom_random(lang, msg, wiki, reaction, spoiler) {
 }
 
 function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
-	got.get( wiki + 'api.php?action=query&meta=allmessages|siteinfo&ammessages=custom-Wiki_Manager&amenableparser=true&siprop=general|statistics&titles=Special:Statistics&format=json', {
+	got.get( wiki + 'api.php?action=query&meta=allmessages|siteinfo&ammessages=custom-Wiki_Manager|custom-GamepediaNotice&amenableparser=true&siprop=general|statistics&titles=Special:Statistics&format=json', {
 		responseType: 'json'
 	} ).then( response => {
 		var body = response.body;
@@ -4010,7 +4044,7 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 				var created = [lang.overview.created, new Date(parseInt(site.created + '000', 10)).toLocaleString(lang.dateformat, timeoptions)];
 				var manager = [lang.overview.manager, site.wiki_managers];
 				var official = [lang.overview.official, ( site.official_wiki ? lang.overview.yes : lang.overview.no )];
-				var crossover = [lang.overview.crossover, ( site.wiki_crossover ? 'https://' + site.wiki_crossover + '/' : '' )];
+				var crossover = [lang.overview.crossover, ( site.wiki_crossover ? '<https://' + site.wiki_crossover + '/>' : '' )];
 				var description = [lang.overview.description, site.wiki_description];
 				var image = [lang.overview.image, site.wiki_image];
 				
@@ -4054,6 +4088,7 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 					var topic = [lang.overview.topic, site.topic];
 					var founder = [lang.overview.founder, site.founding_user_id];
 					var manager = [lang.overview.manager, body.query.allmessages[0]['*']];
+					var crossover = [lang.overview.crossover, ( body.query.allmessages[1]['*'] ? '<https://' + body.query.allmessages[1]['*'] + '.gamepedia.com/>' : '' )];
 					var created = [lang.overview.created, new Date(site.creation_date).toLocaleString(lang.dateformat, timeoptions)];
 					var description = [lang.overview.description, site.desc];
 					var image = [lang.overview.image, site.image];
@@ -4092,11 +4127,17 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 							embed.addField( founder[0], founder[1], true );
 							if ( manager[1] ) embed.addField( manager[0], '[' + manager[1] + '](' + wiki.toLink('User:' + manager[1], '', '', body.query.general, true) + ') ([' + lang.overview.talk + '](' + wiki.toLink('User talk:' + manager[1], '', '', body.query.general, true) + '))', true );
 							embed.addField( created[0], created[1], true ).addField( articles[0], articles[1], true ).addField( pages[0], pages[1], true ).addField( edits[0], edits[1], true ).addField( users[0], users[1], true ).setFooter( lang.overview.inaccurate );
+							if ( crossover[1] ) {
+								var crossoverSite = allSites.find( site => '<https://' + site.wiki_domain + '/>' === crossover[1] );
+								if ( crossoverSite ) embed.addField( crossover[0], '[' + crossoverSite.wiki_display_name + '](' + crossover[1] + ')', true );
+								else embed.addField( crossover[0], crossover[1], true );
+							}
 							if ( description[1] ) embed.addField( description[0], description[1] );
 							if ( image[1] ) embed.addField( image[0], image[1] ).setImage( image[1] );
 						}
 						else {
 							text += '\n' + founder.join(' ') + ( manager[1] ? '\n' + manager.join(' ') : '' ) + '\n' + created.join(' ') + '\n' + articles.join(' ') + '\n' + pages.join(' ') + '\n' + edits.join(' ') + '\n' + users.join(' ');
+							if ( crossover[1] ) text += '\n' + crossover.join(' ');
 							if ( description[1] ) text += '\n' + description.join(' ');
 							if ( image[1] ) {
 								text += '\n' + image.join(' ');
@@ -4113,11 +4154,17 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 						founder[1] = lang.overview.none;
 						if ( msg.showEmbed() ) {
 							embed.addField( founder[0], founder[1], true ).addField( created[0], created[1], true ).addField( articles[0], articles[1], true ).addField( pages[0], pages[1], true ).addField( edits[0], edits[1], true ).addField( users[0], users[1], true ).setFooter( lang.overview.inaccurate );
+							if ( crossover[1] ) {
+								var crossoverSite = allSites.find( site => '<https://' + site.wiki_domain + '/>' === crossover[1] );
+								if ( crossoverSite ) embed.addField( crossover[0], '[' + crossoverSite.wiki_display_name + '](' + crossover[1] + ')', true );
+								else embed.addField( crossover[0], crossover[1], true );
+							}
 							if ( description[1] ) embed.addField( description[0], description[1] );
 							if ( image[1] ) embed.addField( image[0], image[1] ).setImage( image[1] );
 						}
 						else {
 							text += '\n' + founder.join(' ') + '\n' + created.join(' ') + '\n' + articles.join(' ') + '\n' + pages.join(' ') + '\n' + edits.join(' ') + '\n' + users.join(' ');
+							if ( crossover[1] ) text += '\n' + crossover.join(' ');
 							if ( description[1] ) text += '\n' + description.join(' ');
 							if ( image[1] ) {
 								text += '\n' + image.join(' ');
@@ -4192,7 +4239,7 @@ function gamepedia_overview(lang, msg, wiki, reaction, spoiler) {
 }
 
 function fandom_overview(lang, msg, wiki, reaction, spoiler) {
-	got.get( wiki + 'api.php?action=query&meta=allmessages|siteinfo&ammessages=custom-Wiki_Manager&amenableparser=true&siprop=general|statistics|wikidesc&titles=Special:Statistics&format=json', {
+	got.get( wiki + 'api.php?action=query&meta=allmessages|siteinfo&ammessages=custom-Wiki_Manager|custom-GamepediaNotice&amenableparser=true&siprop=general|statistics|wikidesc&titles=Special:Statistics&format=json', {
 		responseType: 'json'
 	} ).then( response => {
 		var body = response.body;
@@ -4229,6 +4276,7 @@ function fandom_overview(lang, msg, wiki, reaction, spoiler) {
 				var topic = [lang.overview.topic, site.topic];
 				var founder = [lang.overview.founder, site.founding_user_id];
 				var manager = [lang.overview.manager, body.query.allmessages[0]['*']];
+				var crossover = [lang.overview.crossover, ( body.query.allmessages[1]['*'] ? '<https://' + body.query.allmessages[1]['*'] + '.gamepedia.com/>' : '' )];
 				var created = [lang.overview.created, new Date(site.creation_date).toLocaleString(lang.dateformat, timeoptions)];
 				var articles = [lang.overview.articles, body.query.statistics.articles];
 				var pages = [lang.overview.pages, body.query.statistics.pages];
@@ -4277,11 +4325,17 @@ function fandom_overview(lang, msg, wiki, reaction, spoiler) {
 						embed.addField( founder[0], founder[1], true );
 						if ( manager[1] ) embed.addField( manager[0], '[' + manager[1] + '](' + wiki.toLink('User:' + manager[1], '', '', body.query.general, true) + ') ([' + lang.overview.talk + '](' + wiki.toLink('User talk:' + manager[1], '', '', body.query.general, true) + '))', true );
 						embed.addField( created[0], created[1], true ).addField( articles[0], articles[1], true ).addField( pages[0], pages[1], true ).addField( edits[0], edits[1], true ).addField( users[0], users[1], true ).setFooter( lang.overview.inaccurate );
+						if ( crossover[1] ) {
+							var crossoverSite = allSites.find( site => '<https://' + site.wiki_domain + '/>' === crossover[1] );
+							if ( crossoverSite ) embed.addField( crossover[0], '[' + crossoverSite.wiki_display_name + '](' + crossover[1] + ')', true );
+							else embed.addField( crossover[0], crossover[1], true );
+						}
 						if ( description[1] ) embed.addField( description[0], description[1] );
 						if ( image[1] ) embed.addField( image[0], image[1] ).setImage( image[1] );
 					}
 					else {
 						text += '\n' + founder.join(' ') + ( manager[1] ? '\n' + manager.join(' ') : '' ) + '\n' + created.join(' ') + '\n' + articles.join(' ') + '\n' + pages.join(' ') + '\n' + edits.join(' ') + '\n' + users.join(' ');
+						if ( crossover[1] ) text += '\n' + crossover.join(' ');
 						if ( description[1] ) text += '\n' + description.join(' ');
 						if ( image[1] ) {
 							text += '\n' + image.join(' ');
@@ -4298,11 +4352,17 @@ function fandom_overview(lang, msg, wiki, reaction, spoiler) {
 					founder[1] = lang.overview.none;
 					if ( msg.showEmbed() ) {
 						embed.addField( founder[0], founder[1], true ).addField( created[0], created[1], true ).addField( articles[0], articles[1], true ).addField( pages[0], pages[1], true ).addField( edits[0], edits[1], true ).addField( users[0], users[1], true ).setFooter( lang.overview.inaccurate );
+						if ( crossover[1] ) {
+							var crossoverSite = allSites.find( site => '<https://' + site.wiki_domain + '/>' === crossover[1] );
+							if ( crossoverSite ) embed.addField( crossover[0], '[' + crossoverSite.wiki_display_name + '](' + crossover[1] + ')', true );
+							else embed.addField( crossover[0], crossover[1], true );
+						}
 						if ( description[1] ) embed.addField( description[0], description[1] );
 						if ( image[1] ) embed.addField( image[0], image[1] ).setImage( image[1] );
 					}
 					else {
 						text += '\n' + founder.join(' ') + '\n' + created.join(' ') + '\n' + articles.join(' ') + '\n' + pages.join(' ') + '\n' + edits.join(' ') + '\n' + users.join(' ');
+						if ( crossover[1] ) text += '\n' + crossover.join(' ');
 						if ( description[1] ) text += '\n' + description.join(' ');
 						if ( image[1] ) {
 							text += '\n' + image.join(' ');
@@ -4799,7 +4859,7 @@ function discussion_formatting(jsonModel) {
 			description += prepend + jsonModel.text.escapeFormatting() + append;
 			break;
 		case 'image':
-			description += '{@' + jsonModel.attrs.id + '}\n';
+			if ( jsonModel.attrs.id !== null ) description += '{@' + jsonModel.attrs.id + '}\n';
 			break;
 		case 'code_block':
 			description += '```\n';
@@ -5169,14 +5229,16 @@ function newMessage(msg, wiki = defaultSettings.wiki, lang = i18n[defaultSetting
 						cmd_link(lang, msg, args.join(' '), 'https://' + invoke.substring(1) + '.gamepedia.com/', ' ' + invoke + ' ');
 					}
 					else if ( /^\?(?:[a-z-]{1,8}\.)?[a-z\d-]{1,50}$/.test(invoke) ) {
-						if ( invoke.includes( '.' ) ) wiki = 'https://' + invoke.split('.')[1] + '.fandom.com/' + invoke.substring(1).split('.')[0] + '/';
-						else wiki = 'https://' + invoke.substring(1) + '.fandom.com/';
-						cmd_link(lang, msg, args.join(' '), wiki, ' ' + invoke + ' ');
+						var invokeWiki = wiki;
+						if ( invoke.includes( '.' ) ) invokeWiki = 'https://' + invoke.split('.')[1] + '.fandom.com/' + invoke.substring(1).split('.')[0] + '/';
+						else invokeWiki = 'https://' + invoke.substring(1) + '.fandom.com/';
+						cmd_link(lang, msg, args.join(' '), invokeWiki, ' ' + invoke + ' ');
 					}
 					else if ( /^\?\?(?:[a-z-]{1,8}\.)?[a-z\d-]{1,50}$/.test(invoke) ) {
-						if ( invoke.includes( '.' ) ) wiki = 'https://' + invoke.split('.')[1] + '.wikia.org/' + invoke.substring(2).split('.')[0] + '/';
-						else wiki = 'https://' + invoke.substring(2) + '.wikia.org/';
-						cmd_link(lang, msg, args.join(' '), wiki, ' ' + invoke + ' ');
+						var invokeWiki = wiki;
+						if ( invoke.includes( '.' ) ) invokeWiki = 'https://' + invoke.split('.')[1] + '.wikia.org/' + invoke.substring(2).split('.')[0] + '/';
+						else invokeWiki = 'https://' + invoke.substring(2) + '.wikia.org/';
+						cmd_link(lang, msg, args.join(' '), invokeWiki, ' ' + invoke + ' ');
 					}
 					else cmd_link(lang, msg, line.split(' ').slice(1).join(' '), wiki);
 				}