IdlePixel Custom Interactor

Sends, receives, and displays CUSTOM websocket frames

当前为 2023-11-27 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name IdlePixel Custom Interactor
  3. // @namespace lbtechnology.info
  4. // @version 2.2.0
  5. // @description Sends, receives, and displays CUSTOM websocket frames
  6. // @author Lux-Ferre
  7. // @license MIT
  8. // @match *://idle-pixel.com/login/play*
  9. // @grant none
  10. // @require https://greasyfork.org/scripts/441206-idlepixel/code/IdlePixel+.js?anticache=20220905
  11. // ==/UserScript==
  12. (function() {
  13. 'use strict';
  14. class CustomInteractorPlugin extends IdlePixelPlusPlugin {
  15. constructor() {
  16. super("custominteractor", {
  17. about: {
  18. name: GM_info.script.name,
  19. version: GM_info.script.version,
  20. author: GM_info.script.author,
  21. description: GM_info.script.description
  22. },
  23. config: [
  24. {
  25. id: "receiver",
  26. label: "Default account to send custom messages to.",
  27. type: "string",
  28. max: 20,
  29. default: ""
  30. },
  31. {
  32. id: "textareaLines",
  33. label: "Number of messages to keep in pseudo-console (0 for all.) Under 30 will shrink console.",
  34. type: "integer",
  35. min: 0,
  36. max: 500,
  37. default: 0
  38. },
  39. {
  40. id: "ignorePluginList",
  41. label: "List of plugins to ignore customs from (comma separated.)",
  42. type: "string",
  43. max: 2000,
  44. default: ""
  45. },
  46. {
  47. id: "defaultCommandList",
  48. label: "List of preset commands for the command dropdown (comma separated.)",
  49. type: "string",
  50. max: 2000,
  51. default: ""
  52. },
  53. {
  54. id: "pluginOverride",
  55. label: "Overrides the plugin value in the custom message.",
  56. type: "string",
  57. max: 20,
  58. default: ""
  59. },
  60. {
  61. id: "rememberCommand",
  62. label: "Remember last used command in pseudo-console?",
  63. type: "boolean",
  64. default: false
  65. }
  66. ]
  67. });
  68. this.previous = "";
  69. }
  70.  
  71. createPanel(){
  72. const maxRowNumber = this.getConfig("textareaLines")
  73. let rowNumber = maxRowNumber
  74. if (maxRowNumber >= 30 || maxRowNumber === 0){
  75. rowNumber = 30
  76. }
  77.  
  78. IdlePixelPlus.addPanel("interactor", "Custom Message Interactor", function() {
  79. const content = `
  80. <div>
  81. <div class="d-flex">
  82. <div class="me-auto">
  83. <label for='interactor_recipient' class="interactor-label">Recipient:&nbsp&nbsp</label>
  84. <input type="text" id="interactor_recipient">
  85. </div>
  86. <div class="">
  87. <label for='interactor_plugin_overrride' class="interactor-label">Plugin Override:&nbsp&nbsp</label>
  88. <input type="text" id="interactor_plugin_overrride">
  89. </div>
  90. </div>
  91. <div class="d-flex">
  92. <textarea id="customs_received" wrap="soft" class="w-100" rows="${rowNumber}" readonly>${'\n'.repeat(rowNumber)}</textarea>
  93. </div>
  94. <form onsubmit='event.preventDefault(); IdlePixelPlus.plugins.custominteractor.sendCustom()'>
  95. <datalist id="interactorCommandList"></datalist>
  96. <div class="d-flex flex-fill">
  97. <div class="col-3">
  98. <input type="text" class="w-100" list="interactorCommandList" id="interactor_command_in" placeholder="command">
  99. </div>
  100. <div class="col-8">
  101. <input type="text" class="w-100" id="interactor_payload_in" placeholder="payload">
  102. </div>
  103. <div class="col-1">
  104. <input type="submit" class="w-100" value="Send">
  105. </div>
  106. </div>
  107. </form>
  108. </div>
  109. `
  110. return content
  111. });
  112. }
  113.  
  114. onLogin(){
  115. const onlineCount = $(".top-bar .gold:not(#top-bar-admin-link)");
  116. onlineCount.before(`
  117. <a href="#" class="hover float-end link-no-decoration" onclick="event.preventDefault(); IdlePixelPlus.setPanel('interactor')" title="Custom Message Interactor">Custom&nbsp;&nbsp;&nbsp;</a>
  118. `);
  119. this.createPanel()
  120. this.setConfigValuesToUI()
  121.  
  122. if ("ui-tweaks" in IdlePixelPlus.plugins){
  123. this.applyTheme("UIT")
  124. } else {
  125. this.applyTheme("default")
  126. }
  127. }
  128.  
  129. onConfigsChanged(){
  130. this.setConfigValuesToUI()
  131. }
  132.  
  133. onCustomMessageReceived(player, content, callbackId) {
  134. const customData = this.parseCustom(player, content, callbackId)
  135.  
  136. const rawIgnoreList = this.getConfig("ignorePluginList").toLowerCase()
  137. const ignoreList = rawIgnoreList.split(',');
  138. if (ignoreList[0] === ""){ignoreList.shift()}
  139.  
  140. if (ignoreList.includes(customData.plugin.toLowerCase())){
  141. return
  142. }
  143. let IdString = "-1"
  144.  
  145. if (customData.callbackId){
  146. IdString = customData.callbackId
  147. }
  148.  
  149. const output_string = `[${IdString}]${player}: ${customData.plugin}: ${customData.command}: ${customData.payload}`
  150. console.log(output_string)
  151. this.addToPseudoConsole(output_string)
  152. }
  153.  
  154. setConfigValuesToUI(){
  155. $("#interactor_recipient").val(this.getConfig("receiver"))
  156. $("#interactor_plugin_overrride").val(this.getConfig("pluginOverride"))
  157.  
  158. const maxRows = this.getConfig("textareaLines")
  159. const textOutput = $("#customs_received")
  160.  
  161. if (maxRows >=30 || maxRows === 0){
  162. textOutput.attr("rows", 30)
  163. } else {
  164. textOutput.attr("rows", maxRows)
  165. }
  166.  
  167. const commandDatalist = $("#interactorCommandList")
  168. let commandList = this.getConfig("defaultCommandList").split(",")
  169. if (commandList[0]===""){
  170. commandList.shift()
  171. }
  172.  
  173. commandDatalist.empty()
  174.  
  175. commandList.forEach((command) => {
  176. commandDatalist.append(`<option value="${command}">`)
  177. })
  178. }
  179.  
  180. parseCustom(player, content, callbackId){
  181. const customData = {
  182. player: player,
  183. callbackId: callbackId,
  184. anwinFormatted: false
  185. }
  186. const splitPayload = content.split(":")
  187. if(splitPayload.length >= 3){
  188. customData.anwinFormatted = true
  189. customData.plugin = splitPayload[0]
  190. customData.command = splitPayload[1]
  191. customData.payload = splitPayload.slice(2).join(":")
  192. } else {
  193. customData.anwinFormatted = false
  194. customData.plugin = "unknown"
  195. customData.command = "unknown"
  196. customData.payload = content
  197. }
  198.  
  199. return customData
  200.  
  201. }
  202. addToPseudoConsole(output_string){
  203. const textOutput = $("#customs_received")
  204. const lines = textOutput.val().split('\n')
  205. const maxLines = this.getConfig("textareaLines")
  206. lines.push(output_string)
  207. if(lines.length > maxLines && maxLines !== 0){
  208. lines.shift()
  209. }
  210. if (lines[0] === "" && lines.length > 30){
  211. lines.shift()
  212. }
  213.  
  214. const newText = lines.join('\n')
  215. textOutput.val(newText)
  216. textOutput.scrollTop(textOutput[0].scrollHeight);
  217. }
  218. applyTheme(theme){
  219. let backgroundColour = "#ffffff"
  220. let textColour = "#000000"
  221. let labelColour = "#000000"
  222. if (theme==="UIT"){
  223. backgroundColour = IdlePixelPlus.plugins["ui-tweaks"].config["color-chat-area"]
  224. textColour = IdlePixelPlus.plugins["ui-tweaks"].config["font-color-chat-area"]
  225. labelColour = IdlePixelPlus.plugins["ui-tweaks"].config["font-color-panels"]
  226. }
  227.  
  228. $(".interactor-label").css({"color": labelColour})
  229. $("#customs_received").css({"color": textColour, "background-color": backgroundColour})
  230. }
  231.  
  232. sendCustom(){
  233. const recipient = $("#interactor_recipient").val()
  234.  
  235. const commandjQuery = $("#interactor_command_in")
  236. const command = commandjQuery.val()
  237.  
  238. if (!this.getConfig("rememberCommand")){
  239. commandjQuery.val("")
  240. }
  241.  
  242. const datajQuery = $("#interactor_payload_in")
  243. const data = datajQuery.val()
  244. datajQuery.val("")
  245.  
  246. let pluginValue = $("#interactor_plugin_overrride").val()
  247. if (pluginValue === ""){
  248. pluginValue = "interactor"
  249. }
  250.  
  251. let content = ""
  252.  
  253. if (data !== ""){
  254. content = `${pluginValue}:${command}:${data}`
  255. } else {
  256. content = `${pluginValue}:${command}`
  257. }
  258.  
  259. const payload = {
  260. content: content,
  261. onResponse: function(player, content, callbackId) {
  262. return true;
  263. },
  264. onOffline: function(player, content) {
  265. console.log(content)
  266. },
  267. timeout: 2000 // callback expires after 2 seconds
  268. }
  269. IdlePixelPlus.sendCustomMessage(recipient, payload)
  270. }
  271. }
  272. const plugin = new CustomInteractorPlugin();
  273. IdlePixelPlus.registerPlugin(plugin);
  274. })();