DiscordFreeEmojis

Link emojis if you don't have nitro!

  1. // ==UserScript==
  2. // @name DiscordFreeEmojis
  3. // @namespace https://gitlab.com/An0/DiscordFreeEmojis
  4. // @version 1.6.0.0
  5. // @description Link emojis if you don't have nitro!
  6. // @author An0
  7. // @license LGPLv3 - https://www.gnu.org/licenses/lgpl-3.0.txt
  8. // @match https://*.discord.com/channels/*
  9. // @match https://*.discord.com/activity
  10. // @match https://*.discord.com/login*
  11. // @match https://*.discord.com/app
  12. // @match https://*.discord.com/library
  13. // @match https://*.discord.com/store
  14. // @grant unsafeWindow
  15. // ==/UserScript==
  16.  
  17.  
  18. (function() {
  19.  
  20. 'use strict';
  21.  
  22. const BaseColor = "#0cf";
  23.  
  24. var Discord;
  25. var Utils = {
  26. Log: (message) => { console.log(`%c[FreeEmojis] %c${message}`, `color:${BaseColor};font-weight:bold`, "") },
  27. Warn: (message) => { console.warn(`%c[FreeEmojis] %c${message}`, `color:${BaseColor};font-weight:bold`, "") },
  28. Error: (message) => { console.error(`%c[FreeEmojis] %c${message}`, `color:${BaseColor};font-weight:bold`, "") },
  29. Webpack: function() {
  30. if(this.cachedWebpack) return this.cachedWebpack;
  31.  
  32. let webpackExports;
  33.  
  34. if(typeof BdApi !== "undefined" && BdApi?.findModuleByProps && BdApi?.findModule) {
  35. return this.cachedWebpack = { findModule: BdApi.findModule, findModuleByUniqueProperties: (props) => BdApi.findModuleByProps.apply(null, props) };
  36. }
  37. else if(Discord.window.webpackChunkdiscord_app != null) {
  38. const ids = ['__extra_id__'];
  39. Discord.window.webpackChunkdiscord_app.push([
  40. ids,
  41. {},
  42. (req) => {
  43. webpackExports = req;
  44. ids.length = 0;
  45. }
  46. ]);
  47. }
  48. else if(Discord.window.webpackJsonp != null) {
  49. webpackExports = typeof(Discord.window.webpackJsonp) === 'function' ?
  50. Discord.window.webpackJsonp(
  51. [],
  52. { '__extra_id__': (module, _export_, req) => { _export_.default = req } },
  53. [ '__extra_id__' ]
  54. ).default :
  55. Discord.window.webpackJsonp.push([
  56. [],
  57. { '__extra_id__': (_module_, exports, req) => { _module_.exports = req } },
  58. [ [ '__extra_id__' ] ]
  59. ]);
  60.  
  61. delete webpackExports.m['__extra_id__'];
  62. delete webpackExports.c['__extra_id__'];
  63. }
  64. else return null;
  65.  
  66. const findModule = (filter) => {
  67. for(let i in webpackExports.c) {
  68. if(webpackExports.c.hasOwnProperty(i)) {
  69. let m = webpackExports.c[i].exports;
  70.  
  71. if(!m) continue;
  72.  
  73. if(m.__esModule && m.default) m = m.default;
  74.  
  75. if(filter(m)) return m;
  76. }
  77. }
  78.  
  79. return null;
  80. };
  81.  
  82. const findModuleByUniqueProperties = (propNames) => findModule(module => propNames.every(prop => module[prop] !== undefined));
  83.  
  84. return this.cachedWebpack = { findModule, findModuleByUniqueProperties };
  85. }
  86. };
  87.  
  88.  
  89. function Init(final)
  90. {
  91. Discord = { window: (typeof(unsafeWindow) !== 'undefined') ? unsafeWindow : window };
  92.  
  93. const webpackUtil = Utils.Webpack();
  94. if(webpackUtil == null) { if(final) Utils.Error("Webpack not found."); return 0; }
  95. const { findModule, findModuleByUniqueProperties } = webpackUtil;
  96.  
  97. let emojisModule = findModuleByUniqueProperties([ 'getDisambiguatedEmojiContext', 'searchWithoutFetchingLatest' ]);
  98. if(emojisModule == null) { if(final) Utils.Error("emojisModule not found."); return 0; }
  99.  
  100. let messageEmojiParserModule = findModuleByUniqueProperties([ 'parse', 'parsePreprocessor', 'unparse' ]);
  101. if(messageEmojiParserModule == null) { if(final) Utils.Error("messageEmojiParserModule not found."); return 0; }
  102.  
  103. let emojiPickerModule = findModuleByUniqueProperties([ 'useEmojiSelectHandler' ]);
  104. if(emojiPickerModule == null) { if(final) Utils.Error("emojiPickerModule not found."); return 0; }
  105.  
  106. const original_searchWithoutFetchingLatest = emojisModule.searchWithoutFetchingLatest;
  107. emojisModule.searchWithoutFetchingLatest = function() {
  108. let result = original_searchWithoutFetchingLatest.apply(this, arguments);
  109. result.unlocked.push(...result.locked);
  110. result.locked = [];
  111. return result;
  112. }
  113.  
  114. function replaceEmoji(parseResult, emoji) {
  115. parseResult.content = parseResult.content.replace(`<${emoji.animated ? "a" : ""}:${emoji.originalName || emoji.name}:${emoji.id}>`, emoji.url.split("?")[0] + "?size=48");
  116. }
  117. const original_parse = messageEmojiParserModule.parse;
  118. messageEmojiParserModule.parse = function() {
  119. let result = original_parse.apply(this, arguments);
  120.  
  121. if(result.invalidEmojis.length !== 0) {
  122. for(let emoji of result.invalidEmojis) {
  123. replaceEmoji(result, emoji);
  124. }
  125. result.invalidEmojis = [];
  126. }
  127. let validNonShortcutEmojis = result.validNonShortcutEmojis;
  128. for (let i = 0; i < validNonShortcutEmojis.length; i++) {
  129. const emoji = validNonShortcutEmojis[i];
  130. if(!emoji.available) {
  131. replaceEmoji(result, emoji);
  132. validNonShortcutEmojis.splice(i, 1);
  133. i--;
  134. }
  135. }
  136.  
  137. return result;
  138. };
  139.  
  140. const original_useEmojiSelectHandler = emojiPickerModule.useEmojiSelectHandler;
  141. emojiPickerModule.useEmojiSelectHandler = function(args) {
  142. const { onSelectEmoji, closePopout } = args;
  143. const originalHandler = original_useEmojiSelectHandler.apply(this, arguments);
  144. return function(data, state) {
  145. if(state.toggleFavorite)
  146. return originalHandler.apply(this, arguments);
  147. const emoji = data.emoji;
  148. if(emoji != null) {
  149. onSelectEmoji(emoji, state.isFinalSelection);
  150. if(state.isFinalSelection) closePopout();
  151. }
  152. };
  153. };
  154.  
  155. Utils.Log("loaded");
  156.  
  157. return 1;
  158. }
  159.  
  160.  
  161. var InitFails = 0;
  162. function TryInit()
  163. {
  164. if(Init() !== 0) return;
  165.  
  166. window.setTimeout((++InitFails === 600) ? Init : TryInit, 100, true);
  167. };
  168.  
  169.  
  170. TryInit();
  171.  
  172. })();