IdlePixel Private Messages

Adds /m command for private messages. Note that this does not use the /pm command because smitty will (presumably) add that eventually.

  1. // ==UserScript==
  2. // @name IdlePixel Private Messages
  3. // @namespace com.anwinity.idlepixel
  4. // @version 1.0.1
  5. // @description Adds /m command for private messages. Note that this does not use the /pm command because smitty will (presumably) add that eventually.
  6. // @author Anwinity
  7. // @license MIT
  8. // @match *://idle-pixel.com/login/play*
  9. // @grant none
  10. // @require https://gf.qytechs.cn/scripts/441206-idlepixel/code/IdlePixel+.js?anticache=20220905
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. function normalizeUsername(username) {
  17. if(!username) return "";
  18. return username
  19. .trim()
  20. .toLowerCase()
  21. .replace("_", " ");
  22. }
  23.  
  24. function reverseNormalizeUsername(username) {
  25. if(!username) return "";
  26. return username
  27. .trim()
  28. .toLowerCase()
  29. .replace(" ", "_");
  30. }
  31.  
  32. class PMPlugin extends IdlePixelPlusPlugin {
  33. constructor() {
  34. super("pm", {
  35. about: {
  36. name: GM_info.script.name,
  37. version: GM_info.script.version,
  38. author: GM_info.script.author,
  39. description: GM_info.script.description
  40. },
  41. config: [
  42. {
  43. id: "blocked",
  44. label: "Blocked Users (PM only), comma separated",
  45. type: "string",
  46. default: ""
  47. }
  48. ]
  49. });
  50. this.previous = "";
  51. }
  52.  
  53. isBlocked(username) {
  54. username = normalizeUsername(username);
  55. const list = this.getBlocked();
  56. return !!(list.find(s => s === username));
  57. }
  58.  
  59. getBlocked() {
  60. return (this.getConfig("blocked") || "")
  61. .split(/\s*,\s*/g)
  62. .filter(s => !!(s))
  63. .map(s => normalizeUsername(s));
  64. }
  65.  
  66. setBlocked(list) {
  67. let storedConfigs;
  68. try {
  69. storedConfigs = JSON.parse(localStorage.getItem(`idlepixelplus.pm.config`) || "{}");
  70. }
  71. catch(err) {
  72. console.error(`Failed to load configs for plugin with id "pm"`);
  73. storedConfigs = {};
  74. }
  75. list = list.map(s => normalizeUsername(s));
  76. const unique = list.filter((c, i) => list.indexOf(c)===i);
  77. const configValue = unique.join(",");
  78. storedConfigs.blocked = configValue;
  79. localStorage.setItem(`idlepixelplus.pm.config`, JSON.stringify(storedConfigs));
  80. IdlePixelPlus.loadPluginConfigs("pm");
  81. }
  82.  
  83. receivePM(username, message) {
  84. if(!this.isBlocked(username)) {
  85. username = normalizeUsername(username);
  86. $("#chat-area").append(`
  87. <div style="background-color: rgba(0, 255, 20, 0.25)">
  88. <span class="color-green">${Chat._get_time()}</span>
  89. From <a target="_blank" class="chat-username" href="https://idle-pixel.com/hiscores/search?username=${username}">${username}</a>:
  90. ${sanitize_input(message)}
  91. </div>`);
  92. if(Chat._auto_scroll) {
  93. $("#chat-area").scrollTop($("#chat-area")[0].scrollHeight);
  94. }
  95. this.previous = reverseNormalizeUsername(username);
  96. }
  97. }
  98.  
  99. receiveOffline(username) {
  100. $("#chat-area").append(`
  101. <div style="background-color: rgba(0, 255, 20, 0.25)">
  102. <span class="color-green">${Chat._get_time()}</span>
  103. <span>${username} is offline.</span>
  104. </div>`);
  105. if(Chat._auto_scroll) {
  106. $("#chat-area").scrollTop($("#chat-area")[0].scrollHeight);
  107. }
  108. }
  109.  
  110. onCustomMessageReceived(player, content, callbackId) {
  111. if(content.startsWith("PM:")) {
  112. content = content.substring("PM:".length);
  113. this.receivePM(player, content);
  114. }
  115. }
  116.  
  117. sendPM(username, message) {
  118. username = normalizeUsername(username);
  119. if(this.isBlocked(username)) {
  120. $("#chat-area").append(`
  121. <div style="background-color: rgba(0, 255, 20, 0.25)">
  122. <span class="color-green">${Chat._get_time()}</span>
  123. <span>${username} is on your block list. You must remove them before sending them a message.</span>
  124. </div>`);
  125. if(Chat._auto_scroll) {
  126. $("#chat-area").scrollTop($("#chat-area")[0].scrollHeight);
  127. }
  128. return;
  129. }
  130. IdlePixelPlus.sendCustomMessage(username, {
  131. content: `PM:${message}`,
  132. onOffline: () => {
  133. this.receiveOffline(username);
  134. return true;
  135. },
  136. timout: 5000
  137. });
  138. $("#chat-area").append(`
  139. <div style="background-color: rgba(0, 255, 20, 0.25)">
  140. <span class="color-green">${Chat._get_time()}</span>
  141. To <a target="_blank" class="chat-username" href="https://idle-pixel.com/hiscores/search?username=${username}">${username}</a>:
  142. ${sanitize_input(message)}
  143. </div>`);
  144. if(Chat._auto_scroll) {
  145. $("#chat-area").scrollTop($("#chat-area")[0].scrollHeight);
  146. }
  147. this.previous = reverseNormalizeUsername(username);
  148. }
  149.  
  150. block(username) {
  151. username = normalizeUsername(username);
  152. const list = this.getBlocked();
  153. list.push(username);
  154. this.setBlocked(list);
  155.  
  156. $("#chat-area").append(`
  157. <div style="background-color: rgba(0, 255, 20, 0.25)">
  158. <span class="color-green">${Chat._get_time()}</span>
  159. <span>${username} has been blocked.</span>
  160. </div>`);
  161. if(Chat._auto_scroll) {
  162. $("#chat-area").scrollTop($("#chat-area")[0].scrollHeight);
  163. }
  164. }
  165.  
  166. unblock(username) {
  167. username = normalizeUsername(username);
  168. const list = this.getBlocked().filter(s => username != normalizeUsername(s));
  169. this.setBlocked(list);
  170.  
  171. $("#chat-area").append(`
  172. <div style="background-color: rgba(0, 255, 20, 0.25)">
  173. <span class="color-green">${Chat._get_time()}</span>
  174. <span>${username} has been unblocked.</span>
  175. </div>`);
  176. if(Chat._auto_scroll) {
  177. $("#chat-area").scrollTop($("#chat-area")[0].scrollHeight);
  178. }
  179. }
  180.  
  181. onLogin() {
  182.  
  183. if(typeof IdlePixelPlus.registerCustomChatCommand === "function") {
  184. IdlePixelPlus.registerCustomChatCommand("m", (command, message) => {
  185. message = (message||"").trim();
  186. if(!message) {
  187. return;
  188. }
  189. let username;
  190. let space = message.indexOf(" ");
  191. if(space > 0) {
  192. username = message.substring(0, space).trim();
  193. message = message.substring(space).trim();
  194. }
  195. else {
  196. username = message.trim();
  197. message = "";
  198. }
  199. this.sendPM(username, message);
  200. }, "Send private message. Note: Both sender and receiver must have this plugin installed for it to work.<br /><strong>Usage:</strong> /%COMMAND% &lt;username&gt; &lt;message&gt;<br />Use player's username has a space in it, replace the space with an underscore.<br /><strong>Also See: </strong>/mblock /munblock");
  201.  
  202. IdlePixelPlus.registerCustomChatCommand("mblock", (command, message) => {
  203. message = (message||"").trim();
  204. if(!message) {
  205. return;
  206. }
  207. this.block(message);
  208.  
  209. }, "Block PMs from user.<br /><strong>Usage:</strong> /%COMMAND% &lt;username&gt;");
  210.  
  211. IdlePixelPlus.registerCustomChatCommand("munblock", (command, message) => {
  212. message = (message||"").trim();
  213. if(!message) {
  214. return;
  215. }
  216. this.unblock(message);
  217.  
  218. }, "Unblock PMs from user.<br /><strong>Usage:</strong> /%COMMAND% &lt;username&gt;");
  219.  
  220. $("#chat-area-input").on("keydown", (event) => {
  221. const input = $("#chat-area-input");
  222. if(event.which==9 || event.keyCode==9) {
  223. event.preventDefault();
  224. let val = input.val() || "";
  225. if(!val.startsWith("/")) {
  226. if(this.previous) {
  227. val = `/m ${this.previous} ${val}`;
  228. }
  229. else {
  230. val = `/m ${val}`;
  231. }
  232. input.val(val);
  233. }
  234. }
  235. });
  236. }
  237.  
  238.  
  239.  
  240. }
  241.  
  242.  
  243.  
  244.  
  245. }
  246.  
  247. const plugin = new PMPlugin();
  248. IdlePixelPlus.registerPlugin(plugin);
  249.  
  250. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址