ANWH:Agar通知Webhooks

Agar サーバー情報を Webhooks(例えばDiscord) に通知します

  1. // ==UserScript==
  2. // @name ANWH:Agar通知Webhooks
  3. // @name:ja ANWH:Agar通知Webhooks
  4. // @name:en ANWH:Agar info⇒Webhooks
  5. // @version 0.2
  6. // @namespace http://tampermonkey.net/tannichi-anwh
  7. // @description Agar サーバー情報を Webhooks(例えばDiscord) に通知します
  8. // @description:ja Agar サーバー情報を Webhooks(例えばDiscord) に通知します
  9. // @description:en notify Agar-server-info to Webhooks(e.g.Discord)
  10. // @author tannichi
  11. // @match http://agar.io/*
  12. // @match https://www.google.co.jp/uDV1b4P4
  13. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js
  14. // @grant unsafeWindow
  15. // @grant GM_xmlhttpRequest
  16. // @grant GM_setValue
  17. // @grant GM_getValue
  18. // ==/UserScript==
  19.  
  20. (function() {
  21. 'use strict';
  22. const global = window.unsafeWindow || window;
  23. let my = {
  24. "name": "AgarNoticeWebhooks",
  25. "id": "anwh",
  26. "log": function(msg){ console.log(this.name + ":"+ msg); }
  27. };
  28. let stat = {
  29. "prof_num": 2,
  30. "config_url": "https://www.google.co.jp/uDV1b4P4",
  31. "symbol_empty": "?",
  32. "symbol_done": "?",
  33. };
  34. let cfg = {}, cfg_org = {
  35. "p1_use": true,
  36. "p1_msg": "@everyone come hear!",
  37. };
  38.  
  39. // ===== 初期処理 ====
  40. function initialize(){
  41. global[my.id] = {my:my, stat:stat, cfg:cfg};
  42. var local_style = '';
  43. local_style += '#anwh-cfg-dlg {';
  44. //local_style += ' border-radius:0; font-size: 80%; padding: 2px 10px; position: fixed;';
  45. //local_style += ' pointer-events: auto; background-color: rgba(32,32,32,0.4); color: #ffffff;';
  46. //local_style += ' overflow: hidden;';
  47. local_style += '}';
  48. local_style += '#anwh-dialog input, #anwh-dialog label {';
  49. local_style += ' width: auto; user-select: auto!important; pointer-events: auto;';
  50. local_style += ' position: relative; float: initial;';
  51. local_style += ' color: initial; background-color: initial; border: initial;';
  52. //local_style += ' display: run-in;'; // NG
  53. local_style += '}';
  54. local_style += '#anwh-dialog input[type="text"] {';
  55. local_style += ' border: solid;';
  56. local_style += '}';
  57. $("head").append('<style>\n'+ local_style +'\n</style>');
  58. // --- コントローラーの挿入先を探す ----
  59. let htmlSet = null;
  60. if($("#settingsButton").length){ // orginal+ AgarTool
  61. htmlSet = function(html){
  62. $("#settingsButton").before(html);
  63. };
  64. }else if($(".btn-play").length){ // OGARio
  65. htmlSet = function(html){
  66. $(".btn-play").before(html);
  67. };
  68. }else{ // unknown
  69. htmlSet = function(html){
  70. $("#nick")[0].after(html);
  71. };
  72. }
  73. let html = '';
  74. html += '<div id="anwh-controller">';
  75. html += '<span title="Agar Notice Webhooks">anwh:</span>';
  76. html += '<span id="anwh-notice">?</span>';
  77. html += '<span id="anwh-config">?</span>';
  78. html += '</div>';
  79. htmlSet(html);
  80. $("#anwh-notice").click(function(event){
  81. my.log("notice click");
  82. stat.notice = ! stat.notice;
  83. if(stat.notice){
  84. $("#anwh-notice").text('⏳');
  85. my.notice_start();
  86. }else{
  87. $("#anwh-notice").text('?');
  88. my.notice_stop();
  89. }
  90. });
  91. $("#anwh-config").click(my.config);
  92. my.config_apply();
  93. }
  94.  
  95. // ===== 通知処理 ====
  96. my.notice_start = function(){
  97. // 画面からトークンが取得できれば、即送信する
  98. let tokenElem = $("#server-token,#server");
  99. if(tokenElem.length){
  100. my.notice_send(tokenElem.val());
  101. return;
  102. }
  103. my.notice_token_detect();
  104. };
  105. my.notice_stop = function(){
  106. };
  107. my.notice_send = function(token){
  108. let flg0 = {"token": token};
  109. let flg_list = [flg0];
  110. for(let name in cfg){
  111. let res = /^p(\d+)_(.*)/.exec(name);
  112. if(res){
  113. let prof_no = res[1];
  114. let prof_name = res[2];
  115. if(!(prof_no in flg_list)){
  116. flg_list[prof_no] = {"no": prof_no};
  117. }
  118. flg_list[prof_no][prof_name] = cfg[name];
  119. }
  120. }
  121. if(cfg.leaderboard){
  122. if($("#leaderboard-positions").length){ // OGARio
  123. flg0.leaderboard = $("#leaderboard-positions").text();
  124. }else if($("#leaderboard").length){ // AgarTool
  125. flg0.leaderboard = $("#leaderboard").val();
  126. }
  127. }
  128. if(cfg.tag){
  129. flg0.tag = $('#clantag,#tag,#psk').val() || "<none>";
  130. }
  131. stat.send_count = 0;
  132. for(let prof_no = 1; prof_no < flg_list.length; prof_no ++){
  133. let flg = {};
  134. //Object.assign(flg, flg_list[0], flg_list[prof_no]);
  135. my.flg_merge(flg, flg_list[0]);
  136. my.flg_merge(flg, flg_list[prof_no]);
  137. my.notice_send_sub(flg);
  138. }
  139. if(stat.send_count === 0){
  140. $("#anwh-notice").text(stat.symbol_empty);
  141. }
  142. };
  143. my.flg_merge = function(dst, src){
  144. for(let name in src){
  145. let value = src[name];
  146. if(typeof value !== "string" || value){
  147. dst[name] = value;
  148. }
  149. }
  150. };
  151. my.notice_send_sub = function(flg){
  152. if(! flg.webhooksUrl || ! flg.use){
  153. return;
  154. }
  155. let dataObj = {};
  156. dataObj.content = (''+
  157. (flg.msg || "")+
  158. "\ntoken:"+ flg.token+
  159. (cfg.tag ? " tag:"+ flg.tag : "")+
  160. (cfg.leaderboard ? "\n"+"lb:"+ flg.leaderboard : ""))
  161. .replace(/^\n/, "")
  162. .replace(/\n\n/g, "\n");
  163. let nick = flg.nick || $("#nick").val();
  164. if(nick){
  165. dataObj.username = nick;
  166. }
  167. if(flg.avatar){
  168. dataObj.avatar_url = flg.avatar;
  169. }
  170. var dataStr = JSON.stringify(dataObj);
  171. my.log("notice data="+ dataStr);
  172. var xhr = new XMLHttpRequest();
  173. xhr.open("POST", flg.webhooksUrl, true);
  174. xhr.setRequestHeader("Content-type", "application/json");
  175. xhr.onreadystatechange = function () {
  176. if(xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 204)) {
  177. //var json = JSON.parse(xhr.responseText);
  178. //console.log("OK email=" + json.email + ", pass=" + json.password);
  179. stat.send_count --;
  180. if(stat.send_count === 0){
  181. $("#anwh-notice").text(stat.symbol_done);
  182. }
  183. }
  184. };
  185. xhr.send(dataStr);
  186. stat.send_count ++;
  187. };
  188. // ----- 画面に token が無い場合の処理 -----
  189. my.notice_token_detect = function(){
  190. let save_name = my.id +"_save_send";
  191. let SockProt = global.WebSocket.prototype;
  192. if(save_name in SockProt){
  193. my.log("WebSocket.send already hooked");
  194. return;
  195. }
  196. let save_send = SockProt[save_name] = global.WebSocket.prototype.send;
  197. let urlRe = /^ws:\/\/live-arena-(\w+)\.agar\.io/;
  198. global.WebSocket.prototype.send = function(data){
  199. save_send.apply(this, [data]);
  200. let res = urlRe.exec(this.url);
  201. my.log("catch send url="+ this.url +" res="+ res);
  202. if(res){
  203. global.WebSocket.prototype.send = save_send;
  204. delete SockProt[save_name];
  205. my.notice_send(res[1]);
  206. }
  207. };
  208. };
  209.  
  210. // ===== 設定画面 ====
  211. my.config = function(){
  212. my.log("config clicked");
  213. if(! stat.config_show){
  214. my.config_sub();
  215. }
  216. stat.config_show();
  217. };
  218. my.config_sub = function(){
  219. let html = '';
  220. html += '<div id="anwh-cfg-parent" style="display:none;">';
  221. html += '<dialog id="anwh-dialog"></dialog>';
  222. html += '</div>';
  223. $("#anwh-config").after(html);
  224. let dlg = $("#anwh-dialog");
  225. if(dlg.length && dlg.get(0).showModal){
  226. stat.config_show = function(){
  227. my.cfg_init();
  228. my.cfg_load(cfg);
  229. dlg.get(0).showModal();
  230. };
  231. }else{
  232. stat.config_show = function(){
  233. my.cfg_init();
  234. my.cfg_load(cfg);
  235. window.open(stat.config_url);
  236. };
  237. return;
  238. }
  239. html = '';
  240. html += '<span id="anwh-cfg-before">Agar info⇒Webhooks</span>';
  241. dlg.append(html);
  242. my.config_init_sub($("#anwh-cfg-before"));
  243. my.config_cancel = function(){
  244. dlg.get(0).close();
  245. };
  246. $("#anwh-cfg-parent").show();
  247. };
  248. my.config_init_sub = function(before){
  249. //let html = '', spsp = '&nbsp;&nbsp;', brsp = '<br/>&nbsp;&nbsp;';
  250. let html = '', spsp = '  ', brsp = '<br/>  ';
  251. html += '<br/>共通設定 ※同名項目は個別設定で上書きされます';
  252. html += brsp +'with: <label><input type="checkbox" data-anwh-config="tag"/>tag</label>';
  253. html += ' <label><input type="checkbox" data-anwh-config="leaderboard"/>leaderboard</label>';
  254. html += brsp +'<input type="text" data-anwh-config="p0_nick" placeholder="Nick" style="width:15em;" />';
  255. html += brsp +'<input type="text" data-anwh-config="p0_msg" placeholder="Message" style="width:15em;" />';
  256. html += brsp +'<input type="text" data-anwh-config="p0_avatar" placeholder="avatar url" style="width:15em;" />';
  257. for(let prof_no = 1; prof_no <= stat.prof_num; prof_no ++){
  258. var prefix = "p"+ prof_no +"_";
  259. html += '<br/><label><input type="checkbox" data-anwh-config="'+ prefix +'use"/>profile'+ prof_no +'</label>';
  260. html += '&nbsp;<input type="text" data-anwh-config="'+ prefix +'title" placeholder="title" style="width:10em;" />';
  261. html += brsp +'<input type="text" data-anwh-config="'+ prefix +'webhooksUrl" placeholder="Webhooks URL" style="width:15em;" />';
  262. html += brsp +'<input type="text" data-anwh-config="'+ prefix +'nick" placeholder="Nick" style="width:15em;" />';
  263. html += brsp +'<input type="text" data-anwh-config="'+ prefix +'msg" placeholder="Message" style="width:15em;" />';
  264. html += brsp +'<input type="text" data-anwh-config="'+ prefix +'avatar" placeholder="avatar url" style="width:15em;" />';
  265. }
  266. html += '<br/>';
  267. html += spsp +'<button id="anwh-cfg-default" class="btn btn-primary">DEFAULT</button>';
  268. html += spsp +'<button id="anwh-cfg-ok" class="btn btn-success">OK</button>';
  269. html += spsp +'<button id="anwh-cfg-cancel" class="btn btn-danger">CANCEL</button>';
  270. before.after(html);
  271. $("#anwh-cfg-default").click(function(){
  272. my.cfg_load(cfg_org);
  273. });
  274. $("#anwh-cfg-ok").click(function(){
  275. cfg = my.cfg_save();
  276. my.storage_setValue("config", JSON.stringify(cfg));
  277. my.config_cancel();
  278. my.config_apply();
  279. });
  280. $("#anwh-cfg-cancel").click(function(){
  281. my.config_cancel();
  282. });
  283. };
  284. my.config_apply = function(){
  285. };
  286.  
  287. // ===== その他共通処理 ======
  288. my.cfg_init = function(){
  289. $.extend(cfg, cfg_org, JSON.parse(my.storage_getValue("config",'{}')));
  290. };
  291. my.cfg_save = function(){
  292. var cfg_new = {};
  293. $('[data-anwh-config]').each(function(){
  294. var elem = $(this);
  295. var type = elem.prop('type');
  296. var name = elem.attr('data-anwh-config');
  297. var value;
  298. if(type === "checkbox"){
  299. value = elem.prop('checked');
  300. }else{
  301. value = $(this).val();
  302. }
  303. cfg_new[name] = value;
  304. });
  305. return cfg_new;
  306. };
  307. my.cfg_load = function(cfg_new){
  308. $('[data-anwh-config]').each(function(){
  309. var elem = $(this);
  310. var type = elem.prop('type');
  311. var name = elem.attr('data-anwh-config');
  312. if(cfg_new.hasOwnProperty(name)){
  313. var value = cfg_new[name];
  314. if(type === "checkbox"){
  315. elem.prop('checked', value);
  316. }else{
  317. $(this).val(value);
  318. }
  319. }
  320. });
  321. };
  322. my.storage_getValue = function(name, defval_){
  323. //return global.localStorage[my.name +"_"+ name] || defval_;
  324. return GM_getValue(name, defval_);
  325. //return await GM.getValue(name, JSON.stringify(defval_));
  326. };
  327. my.storage_setValue = function(name, value){
  328. //global.localStorage[my.name +"_"+ name] = value;
  329. GM_setValue(name, value);
  330. //await GM.setValue(name, JSON.stringify(value));
  331. };
  332. // ===== 起動処理 ====
  333. my.cfg_init();
  334. if(/https:\/\/www\.google\.co\.jp\//.test(location.href)){
  335. $('body').html(''+
  336. '<span id="anwh-cfg-before">Agar info⇒Webhooks</span>'+
  337. '');
  338. my.config_init_sub($("#anwh-cfg-before"));
  339. my.cfg_load(cfg);
  340. my.config_cancel = function(){
  341. window.close();
  342. };
  343. return;
  344. }
  345. function pre_loop(){
  346. // この時点では jQuery は使えない
  347. if(! document.getElementById("nick")){
  348. my.pre_loop_timeout = (my.pre_loop_timeout || 1000) + 1000;
  349. setTimeout(pre_loop, my.pre_loop_timeout);
  350. my.log("wait for page load");
  351. return;
  352. }
  353. // 念のため、もう1wait入れる
  354. setTimeout(initialize, 1000);
  355. //loadScript("https://greasyfork.org/scripts/40408-lib-ogario/code/lib%20OGARio.user.js", initialize);
  356. }
  357. pre_loop();
  358. })();