JetBlackHair

EMJack

Jan 16th, 2017
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 60.99 KB | None | 0 0
  1. // ==UserScript==
  2. // @name SHWARTZ99
  3. // @version 's emjack v1.0
  4. // @description some crap you may find useful
  5. // @match https://epicmafia.com/game/*
  6. // @match https://epicmafia.com/lobby
  7. // @namespace https://greasyfork.org/users/4723
  8. // ==/UserScript==
  9.  
  10. // welcome back
  11. function emjack() {
  12.  
  13. // invalid : break
  14. var type=(
  15. window.setup_id ? "mafia" :
  16. window.lobby_id ? "lobby" : ""
  17. );
  18. if(!type) return;
  19.  
  20. // yadayada
  21. var alive=true,
  22. afk=false,
  23. meetd={},
  24. meets={},
  25. master="",
  26. autobomb="",
  27. highlight="",
  28. roulette=0,
  29. kicktimer=0,
  30. keys=0,
  31. auth=false,
  32. notes=null,
  33. users={},
  34. round={};
  35. var ANTIDC=0x0001,
  36. AUKICK=0x0002,
  37. AUWILL=0x0004,
  38. AUBOMB=0x0008,
  39. OBEYME=0x0010,
  40. UNOTES=0x0020,
  41. DEVLOG=0x0040,
  42. JEEVES=0x0080,
  43. SYSALT=0x0100,
  44. MSGMRK=0x0200,
  45. DSPFMT=0x0400,
  46. DSPIMG=0x0800,
  47. GRAPHI=0x4000;
  48. var K_DEBUG=0x0004,
  49. K_SHIFT=0x0008;
  50.  
  51. // public
  52. var user=window.user || "",
  53. ranked=window.ranked===true,
  54. game_id=window.game_id || 0,
  55. setup_id=window.setup_id || localStorage.ejsid || 0,
  56. _emotes=window._emotes || {},
  57. lobby_emotes=window.lobby_emotes || (
  58. window.lobbyinfo ? lobbyinfo.emotes : {}
  59. );
  60. window.ej={
  61. name: "SHWARTZ99",
  62. version: 0x2e,
  63. vstring: "'s emjack v1.0",
  64. cmds: {},
  65. notes: localStorage.notes ?
  66. JSON.parse(localStorage.notes) : {},
  67. users: users,
  68. settings: +localStorage.ejs || AUKICK | UNOTES | MSGMRK | DSPFMT,
  69. };
  70. notes=ej.notes;
  71. afk=(ej.settings & JEEVES)===JEEVES;
  72. if(type==="mafia" && ej.settings & GRAPHI) {
  73. window.OFFSET_LEFT=0;
  74. document.getElementById("game_container").classList.add("graphi");
  75. document.querySelector("[ng-click=\"mode='graphical'\"]").click();
  76. }
  77.  
  78. // setup role icons
  79. var roleimg=document.createElement("style");
  80. document.head.appendChild(roleimg).type="text/css";
  81. if(localStorage.roleimg) {
  82. setTimeout(function() {
  83. ej.run("icons "+localStorage.roleimg, ej.lchat);
  84. });
  85. }
  86.  
  87. // update
  88. if(!localStorage.ejv) {
  89. ej.settings|=DSPFMT;
  90. localStorage.ejv=0x2d;
  91. }
  92. if(localStorage.ejv<0x2e) {
  93. ej.settings|=MSGMRK;
  94. localStorage.ejv=0x2e;
  95. }
  96.  
  97. // plug in
  98. var sock={ socket: null },
  99. postjackl=[];
  100. function postjack() {
  101. var args=[];
  102. for(var i=0; i<arguments.length-1; i++) {
  103. args[i]=arguments[i];
  104. }
  105. postjackl.push(args, arguments[i]);
  106. };
  107. function postjack_run() {
  108. while(postjackl.length) {
  109. postjackl.pop().apply(null, postjackl.pop());
  110. }
  111. };
  112. WebSocket.prototype.send=function(initial) {
  113. return function() {
  114. if(sock.socket!==this) {
  115. sock.build(this);
  116. }
  117. arguments[0]=sock.intercept(arguments[0]);
  118. initial.apply(this, arguments);
  119. };
  120. }(WebSocket.prototype.send);
  121.  
  122. // socket
  123. sock.build=function(socket) {
  124. this.socket=socket;
  125. if(type==="mafia") {
  126. log("", "rt emote emote-"+_emotes[arand(Object.keys(_emotes))]);
  127. log(ej.name+ej.vstring+" connected", "rt");
  128. log((ej.settings|65536).toString(2).substring(1));
  129. }
  130. socket.onmessage=function(initial) {
  131. return function(event) {
  132. sock.handle(event.data, event);
  133. if(alive) {
  134. initial.apply(this, arguments);
  135. setTimeout(postjack_run, 200);
  136. }
  137. };
  138. }(socket.onmessage);
  139. };
  140. sock.handle=function(data, event) {
  141. try {
  142. data=JSON.parse(data);
  143. }
  144. catch(error) {
  145. data=null;
  146. }
  147. if(data) {
  148. if(type==="mafia") {
  149. for(var i=0, real=null; i<data.length; i++) {
  150. real=sock.parseShort(data[i][0], data[i][1]);
  151. if(ej.settings & DEVLOG) {
  152. console.log(" > %s:", real[0], real[1]);
  153. }
  154. if(ej.cmds[real[0]]) {
  155. ej.cmds[real[0]].call(ej, real[1], event);
  156. }
  157. else if(real[0] && real[0][0]==="~") {
  158. ej.cmds["~"].call(ej, real[0], event);
  159. }
  160. }
  161. }
  162. else {
  163. for(var i=0; i<data.length; i+=2) {
  164. if(ej.ccmds[data[i]]) {
  165. ej.ccmds[data[i]].apply(ej, data[i+1]);
  166. }
  167. }
  168. }
  169. }
  170. };
  171. sock.intercept=function(data) {
  172. if(data[0]==="[") {
  173. try {
  174. data=JSON.parse(data);
  175. }
  176. catch(error) {
  177. return data;
  178. }
  179. if(ej.settings & DEVLOG) {
  180. console.log(" < %s:", data[0], data[1]);
  181. }
  182. if(type==="mafia") {
  183. if(ej.cmdi[data[0]]) {
  184. return JSON.stringify([data[0],
  185. ej.cmdi[data[0]](data[1])
  186. ]);
  187. }
  188. }
  189. else {
  190. if(ej.ccmdi[data[0]]) {
  191. return JSON.stringify(
  192. ej.ccmdi[data[0]].apply(ej, data)
  193. );
  194. }
  195. }
  196. return JSON.stringify(data);
  197. }
  198. return data;
  199. };
  200. sock.parseShort=function(cmd, data) {
  201. var rfmt=this.short[cmd];
  202. if(rfmt) {
  203. if(data) for(var key in rfmt.data) {
  204. data[key]=data[rfmt.data[key]] || data[key];
  205. // delete data[rfmt.data[key]];
  206. }
  207. return [rfmt.cmd, data];
  208. }
  209. else {
  210. return [cmd, data];
  211. }
  212. };
  213. sock.short=function(short) {
  214. var rfmt={};
  215. for(var i=0, data=null; i<short.length; i++) {
  216. data=short[i];
  217. rfmt[data.alias || data.cmd]={
  218. cmd: data.cmd || data.alias,
  219. data: data.data
  220. };
  221. }
  222. return rfmt;
  223. }(window.shorten || []);
  224. sock.cmd=function(cmd, data) {
  225. if(sock.socket) {
  226. sock.socket.send(
  227. JSON.stringify([cmd, data])
  228. );
  229. }
  230. };
  231. sock.chat=function(message, data) {
  232. if(typeof data==="object") {
  233. data.msg=message;
  234. data.meet=data.meet || meetd.meet;
  235. sock.cmd("<", data);
  236. }
  237. else sock.cmd("<", {
  238. meet: meetd.meet,
  239. msg: data ? "@"+data+" "+message : message
  240. });
  241. };
  242. sock.vote=function(vote, meeting) {
  243. sock.cmd("point", {
  244. meet: meeting || meetd.meet,
  245. target: vote
  246. });
  247. };
  248. sock.dcthen=function(callback) {
  249. alive=false;
  250. if(type==="mafia") {
  251. ej.redirect_back=callback;
  252. sock.cmd("leave");
  253. WebSocket.prototype.send=function() {};
  254. }
  255. else {
  256. callback();
  257. }
  258. };
  259.  
  260. // packets
  261. ej.cmdi={
  262. "$MODIFY": function(data) {
  263. for(var key in data) {
  264. data[key]=prompt(key, data[key]);
  265. }
  266. return data;
  267. },
  268. "join": function(data) {
  269. if(keys & K_DEBUG) {
  270. keys^=K_DEBUG;
  271. return ej.cmdi.$MODIFY(data);
  272. }
  273. return data;
  274. }
  275. };
  276. ej.cmds={
  277. "~": function(data) {
  278. if(round.state && !ranked) {
  279. if(ej.settings & 0x800000 && !meetd.say && round.state&1===0) {
  280. log("Someone is talking...");
  281. }
  282. }
  283. },
  284. "auth": function(data) {
  285. // owner spectate
  286. var ofg=document.querySelector("#option_fastgame"),
  287. ons=document.querySelector("#option_nospectate");
  288. if(ofg && !ranked && !ofg.classList.contains("sel")) {
  289. ofg.classList.add("sel");
  290. sock.cmd("option", {
  291. field: "fastgame"
  292. });
  293. }
  294. if(ons && !ranked && !ons.classList.contains("sel")) {
  295. ons.classList.add("sel");
  296. sock.cmd("option", {
  297. field: "nospectate"
  298. });
  299. }
  300. postjack(data, function(data) {
  301. auth=true;
  302. ku.send(0, Math.round(ej.version-42));
  303. });
  304. },
  305. "options": function(data) {
  306. // data {anonymous closedroles ... time whisper}
  307. },
  308. "round": function(data) {
  309. // state
  310. round=data;
  311. if(auth && data.state===1) {
  312. if(data.state===1) {
  313. if(ej.settings & AUWILL && !ranked) {
  314. postjack(data, function(data) {
  315. log("Wrote will.", "lastwill");
  316. sock.cmd("will", {
  317. msg: user+"."+u(user).role
  318. });
  319. });
  320. }
  321. }
  322. }
  323. else if((data.state & 1)===0) {
  324. postjack(function() {
  325. var node=null;
  326. for(var x in users) {
  327. node=document.getElementById("id_"+x);
  328. if(node) {
  329. node=node.insertBefore(
  330. document.createElement("span"),
  331. node.firstChild
  332. );
  333. node.id="vc_"+x;
  334. node.textContent=meetd.tally ?
  335. meetd.tally[x] || 0 : 0;
  336. }
  337. }
  338. });
  339. }
  340. },
  341. "users": function(data) {
  342. // chatters users
  343. for(var x in data.users) {
  344. u.make(data.users[x]);
  345. }
  346. postjack(data, function(data) {
  347. var node=null;
  348. for(var x in data.users) {
  349. if(node=document.querySelector("[data-uname='"+x+"']")) {
  350. node.setAttribute("title", notes[x] || "no notes for "+x);
  351. }
  352. }
  353. });
  354. },
  355. "left": function(data) {
  356. // left
  357. for(var i=0; i<data.left.length; i++) {
  358. u(data.left[i]).dead=true;
  359. }
  360. },
  361. "anonymous_players": function(data) {
  362. // players
  363. for(var x in users) {
  364. delete users[x];
  365. }
  366. for(var i=0; i<data.players.length; i++) {
  367. u.make(data.players[i]);
  368. }
  369. },
  370. "anonymous_reveal": function(data) {
  371. // mask user
  372. if(data.user===user) {
  373. u.make(u(this.mask));
  374. }
  375. },
  376. "join": function(data) {
  377. // data user
  378. u.make(data.data);
  379. log(data.user+" has joined");
  380. if(ej.settings & AUKICK && /autokick/i.test(notes[data.user])) {
  381. postjack(data.data.id, function(id) {
  382. sock.cmd("ban", {
  383. uid: id
  384. });
  385. });
  386. }
  387. else {
  388. postjack(data.user, function(user) {
  389. var node=document.querySelector("[data-uname='"+user+"']");
  390. if(node) {
  391. node.setAttribute("title", notes[user] || "no notes for "+user);
  392. }
  393. });
  394. }
  395. },
  396. "leave": function(data) {
  397. // user
  398. if(!data.user) {
  399. data.user=data.u;
  400. }
  401. log(data.user+" has left");
  402. delete users[data.user];
  403. },
  404. "kick": function(data) {
  405. // deranked suicide user
  406. u(data.user).dead=true;
  407. for(var x in meetd.votes) {
  408. if(meetd.votes[x]===data.user) {
  409. data.unpoint=true;
  410. ej.cmds.point(data);
  411. }
  412. }
  413. },
  414. "kill": function(data) {
  415. // target
  416. u(data.target).dead=true;
  417. },
  418. "k": function(data) {
  419. ku.recv(u(data.user || data.u), 1, Date.now());
  420. },
  421. "u": function(data) {
  422. ku.recv(u(data.user || data.u), 0, Date.now());
  423. },
  424. "<": function(data, event) {
  425. // meet msg t user whisper
  426. if(data.user===highlight) {
  427. postjack(function() {
  428. var nodes=document.querySelectorAll(".talk");
  429. if(nodes.length) {
  430. nodes[nodes.length-1].classList.add("ej_highlight");
  431. }
  432. });
  433. }
  434. if(auth && !ranked) {
  435. if(u(data.user).muted) {
  436. postjack(data.user, function(name) {
  437. var nodes=document.querySelectorAll(".talk");
  438. for(var i=0; i<nodes.length; i++) {
  439. if(nodes[i].querySelector("[value='"+name+"']")) {
  440. nodes[i].classList.add("hide");
  441. }
  442. }
  443. });
  444. }
  445. else if(data.msg[0]==="$") {
  446. if(ej.settings & DSPFMT) {
  447. ej.run(data.msg.substring(1), ej.lfmt);
  448. }
  449. }
  450. else if(ej.settings & OBEYME) {
  451. if(data.msg[0]==="@") {
  452. var target=data.msg.replace(/@(\w+).+/, "$1"),
  453. message=data.msg.replace(/@\w+ (.+)/, "$1");
  454. if(target===user) {
  455. ej.run(message, ej.lbot, data);
  456. }
  457. }
  458. }
  459. else if(roulette && data.msg==="@"+user+" roulette") {
  460. ej.run("roulette", ej.lbot, data);
  461. }
  462. }
  463. },
  464. "msg": function() {
  465. var altmsg=[
  466. {
  467. msg: /(\w+) did not leave a will!/,
  468. alt: [
  469. "$1 did not leave a will!",
  470. "$1 never learned to write!",
  471. "$1 was illiterate!",
  472. ]
  473. }
  474. ];
  475. return function(data, event) {
  476. // msg type
  477. for(var i=0, match=null; i<altmsg.length; i++) {
  478. match=altmsg[i].msg.exec(data.msg);
  479. if(match!==null) {
  480. event.data=event.data.replace(
  481. RegExp(match.shift(), "m"),
  482. sformat(arand(altmsg[i].alt), match)
  483. );
  484. break;
  485. }
  486. }
  487. };
  488. }(),
  489. "speech": function(data) {
  490. // data type
  491. if(data.type==="contact") {
  492. postjack(data, function(data) {
  493. log("The roles are... "+data.data.join(", "));
  494. });
  495. }
  496. },
  497. "meet": function(data) {
  498. // basket choosedata data disguise disguise_choices exist
  499. // meet members raw_name say votenoone votesee voteself votetype
  500. data.tally={};
  501. data.votes={};
  502. meets[data.meet]=data;
  503. if(data.say || !meetd.meet) {
  504. meetd=data;
  505. for(var i=0; i<data.members.length; i++) {
  506. u(data.members[i]).meet=data.meet;
  507. }
  508. }
  509. for(var i=0; i<data.basket.length; i++) {
  510. data.tally[data.basket[i]]=0;
  511. }
  512. for(var i=0; i<data.members.length; i++) {
  513. data.votes[data.members[i]]="";
  514. }
  515. if(data.non_voting) {
  516. for(var i=0; i<data.non_voting.length; i++) {
  517. data.votes[data.non_voting[i]]="*";
  518. }
  519. }
  520. if(data.disguise && ej.settings & 0x800000) {
  521. for(var x in data.disguise) {
  522. postjack(x, data.disguise[x], function(fake, name) {
  523. log(fake+" is "+name);
  524. });
  525. }
  526. }
  527. switch(data.meet) {
  528. case "mafia":
  529. if(auth && !data.disguise && !ranked) {
  530. if(false/* ej.settings & OBEYME */) {
  531. postjack(user, function(data) {
  532. sock.chat(u(data).role, {
  533. meet: "mafia"
  534. });
  535. });
  536. }
  537. }
  538. case "thief":
  539. u(user).mafia=true;
  540. for(var x in users) {
  541. if(!data.choosedata[x] && !u(x).dead) {
  542. u(x).mafia=true;
  543. if(x!==user) postjack(x, function(data) {
  544. log(data+" is your partner!");
  545. if(u(x).id) {
  546. document.querySelector("[data-uname='"+data+"'] .roleimg")
  547. .className="roleimg role-mafia";
  548. }
  549. });
  550. }
  551. }
  552. break;
  553. }
  554. },
  555. "end_meet": function(data) {
  556. // meet
  557. if(data.meet===meetd.meet) {
  558. meetd={};
  559. }
  560. delete meets[data.meet];
  561. for(var x in users) {
  562. if(users[x].meet===data.meet) {
  563. if(!users[x].id) {
  564. delete users[x];
  565. }
  566. else if(data.say) {
  567. users[x].meet="";
  568. }
  569. }
  570. }
  571. },
  572. "event": function(data) {
  573. // id
  574. },
  575. "point": function(data) {
  576. // meet target unpoint user
  577. var node=null,
  578. meet=meets[data.meet];
  579. if(meet) {
  580. if(data.unpoint) {
  581. meet.tally[data.target]--;
  582. meet.votes[data.user]="";
  583. }
  584. else {
  585. if(meet.votes[data.user]) {
  586. meet.tally[meet.votes[data.user]]--;
  587. node=document.getElementById("vc_"+meet.votes[data.user]);
  588. if(node) {
  589. node.textContent=meet.tally[meet.votes[data.user]];
  590. }
  591. }
  592. meet.tally[data.target]++;
  593. meet.votes[data.user]=data.target;
  594. }
  595. node=document.getElementById("vc_"+data.target);
  596. if(node) {
  597. node.textContent=meet.tally[data.target];
  598. }
  599. }
  600. },
  601. "reveal": function(data) {
  602. // data red user
  603. u(data.user).role=data.data;
  604. if(!u(data.user).dead) {
  605. if(data.user===user) {
  606. postjack(data, function(data) {
  607. log(data.user===user ?
  608. "Your role is now "+data.data :
  609. data.user+" is a "+data.data
  610. );
  611. });
  612. }
  613. }
  614. },
  615. "disguise": function(data) {
  616. // exchange
  617. },
  618. "countdown": function(data) {
  619. // start totaltime
  620. if(auth && !ranked && ej.settings & AUKICK) {
  621. clearTimeout(kicktimer);
  622. kicktimer=setTimeout(function() {
  623. jeeves.work();
  624. sock.cmd("kick");
  625. }, data.totaltime);
  626. }
  627. },
  628. "kickvote": function() {
  629. clearTimeout(kicktimer);
  630. if(!ranked && ej.settings & AUKICK) {
  631. jeeves.work();
  632. sock.cmd("kick");
  633. }
  634. },
  635. "start_input": function(data) {
  636. // id
  637. if(afk || autobomb || ej.settings & AUBOMB) {
  638. postjack(data, function(data, names) {
  639. sock.cmd("input", {
  640. id: data.id,
  641. input: {
  642. player: autobomb || arand(Object.keys(
  643. meetd.members || users
  644. ))
  645. }
  646. });
  647. });
  648. }
  649. },
  650. "redirect": function(data) {
  651. if(!alive && ej.redirect_back) {
  652. ej.redirect_back();
  653. ej.redirect_back=null;
  654. }
  655. }
  656. };
  657. ej.ccmdi={
  658. "<": function(c, msg) {
  659. if(msg[0]==="/") {
  660. return ["<"];
  661. }
  662. return arguments;
  663. }
  664. };
  665. ej.ccmds={
  666. "<": function(id, msg, t) {
  667. if(msg[0]==="$") {
  668. if(ej.settings & DSPFMT) {
  669. ej.run(msg.substring(1), ej.lfmt);
  670. }
  671. }
  672. }
  673. };
  674.  
  675. // kucode
  676. var ku={};
  677. ku.send=function(op, code) {
  678. code+=op<<6;
  679. if(ej.settings & DEVLOG) {
  680. log(" * "+user+": "+(code|1024).toString(2).substring(1));
  681. }
  682. setTimeout(function() {
  683. for(var i=9; i>=0; i--) {
  684. sock.cmd(code>>i & 1 ? "k" : "u");
  685. }
  686. if(code & 1) {
  687. sock.cmd("u");
  688. }
  689. }, 200);
  690. };
  691. ku.recv=function(u, bit, time) {
  692. if(time-u.kuclock > 100) {
  693. u.kucode=1;
  694. u.kuclock=Infinity;
  695. }
  696. else {
  697. u.kucode<<=1;
  698. u.kucode|=bit;
  699. if(u.kucode & 1024) {
  700. if(ej.settings & DEVLOG) {
  701. log(" * "+u.name+": "+u.kucode.toString(2).substring(1));
  702. }
  703. if(ku.op[u.kucode>>6 & 15]) {
  704. ku.op[u.kucode>>6 & 15]
  705. (u, u.kucode & 63);
  706. }
  707. u.kucode=1;
  708. u.kuclock=Infinity;
  709. }
  710. else {
  711. u.kuclock=time;
  712. }
  713. }
  714. };
  715. ku.op=[
  716. function(u, code) {
  717. if(u.emjack===null) {
  718. u.emjack=(42+code)/10 || 0;
  719. ku.send(0, Math.round(ej.version-42));
  720. }
  721. },
  722. function(u, code) {
  723. ku.send(0, Math.round(ej.version-42));
  724. },
  725. function(u, code) {
  726. if(ej.settings & 0x800000) {
  727. log(u.name+" sent "
  728. +(code|64).toString(2).substring(1)
  729. +":"+code.toString()
  730. +":"+String.fromCharCode(code+96)
  731. );
  732. }
  733. }
  734. ];
  735.  
  736. // jeeves
  737. var jeeves={};
  738. jeeves.work=function() {
  739. if(afk && !ranked) {
  740. for(var x in meets) {
  741. if(!meets[x].votes[user]) {
  742. jeeves.think(meets[x]);
  743. }
  744. }
  745. }
  746. };
  747. jeeves.think=function(meet) {
  748. for(var x in meet.tally) {
  749. if(Math.random() < meet.tally[x]/meet.members.length) {
  750. sock.vote(x, meet.meet);
  751. break;
  752. }
  753. }
  754. if(!meet.votes[user]) {
  755. sock.vote(arand(meet.basket || Object.keys(users)), meet.meet);
  756. }
  757. };
  758.  
  759. // chat base
  760. ej.run=function(input, list, data) {
  761. for(var i=0, match=null; i<list.length; i++) {
  762. match=list[i].regex.exec(input);
  763. if(match!==null) {
  764. data ? match[0]=data : match.shift();
  765. list[i].callback.apply(list[i], match);
  766. break;
  767. }
  768. }
  769. };
  770.  
  771. // chat commands
  772. ej.lfmt=[
  773. {
  774. name: "Display image",
  775. short: "$img [url]",
  776. regex: /^img (.+)/i,
  777. callback: function(url) {
  778. if(ej.settings & DSPIMG) {
  779. postjack(url, function(url) {
  780. var img=new Image(),
  781. node=document.createElement("a");
  782. img.src=url;
  783. node.href=url;
  784. node.target="_blank";
  785. node.appendChild(img);
  786. log(node, "ej_img");
  787. });
  788. }
  789. }
  790. },
  791. {
  792. name: "Display webm",
  793. short: "$webm [url]",
  794. regex: /^webm (.+)/i,
  795. callback: function(url) {
  796. if(ej.settings & DSPIMG) {
  797. postjack(url, function(url) {
  798. var video=document.createElement("video");
  799. video.src=url;
  800. video.setAttribute("controls", "");
  801. video.setAttribute("type", "video/webm");
  802. log(video, "ej_img");
  803. });
  804. }
  805. }
  806. }
  807. ];
  808.  
  809. // chat commands
  810. var lcopy={};
  811. ej.lchat=[
  812. lcopy.sc={
  813. name: "Scriptcheck",
  814. short: "/sc",
  815. regex: /^sc|^scriptcheck/i,
  816. callback: function() {
  817. log(ej.name+ej.vstring);
  818. }
  819. },
  820. {
  821. name: "Native",
  822. regex: /^(me .+)/i,
  823. callback: function(msg) {
  824. sock.chat("/"+msg);
  825. }
  826. },
  827. {
  828. name: "About",
  829. short: "/help",
  830. regex: /^(?:info|help|about) ?(.+)?/i,
  831. callback: function(topic) {
  832. if(this.topics[topic]) {
  833. log(ej.name+ej.vstring+":"+topic, "bold");
  834. for(var i=0; i<this.topics[topic].length; i++) {
  835. log(this.topics[topic][i]);
  836. }
  837. }
  838. else {
  839. log(ej.name+ej.vstring, "bold");
  840. log("Type /cmdlist for a list of commands");
  841. log("Topics (type /help [topic]): ", "lt notop");
  842. log(Object.keys(this.topics).join(", "), "tinyi");
  843. }
  844. },
  845. topics: {
  846. "features": [
  847. "The following passive features are always active...",
  848. "Auto-check boxes \u2767 Clickable links \u2767 Mark mafia partners \u2767 "+
  849. "List agent/spy roles \u2767 Auto-focus & keep chat open \u2767 "+
  850. "Automatically write will (/autowill to toggle) \u2767 etc."
  851. ],
  852. "jeeves": [
  853. "Type /afk to toggle Jeeves or /afk [on/off] to toggle in all games",
  854. "Jeeves will automatically vote for you at the end of the day if you haven't "+
  855. "voted already. He randomly picks a player based on the popular vote (if any)"
  856. ],
  857. "marking": [
  858. "Click on a message to (un)mark it purple (shift+click for orange)"
  859. ],
  860. "ranked": [
  861. "The following features are disabled in ranked games...",
  862. "Auto will \u2767 Auto kick \u2767 Jeeves (afk) \u2767 Fake quoting & reporting \u2767 "+
  863. "Will & death message editing \u2767 Bot mode \u2767 Persistent user notes"
  864. ],
  865. "hotkeys": [
  866. "Ctrl+B: Toggle boxes",
  867. "Ctrl+Q: Quote typed message as yourself"
  868. ]
  869. }
  870. },
  871. lcopy.eval={
  872. name: "Evaluate",
  873. regex: /^eval (.+)/i,
  874. callback: function(input) {
  875. log(JSON.stringify(eval(input)) || "undefined");
  876. }
  877. },
  878. lcopy.clear={
  879. name: "Clear chat, logs, or images",
  880. short: "/clear [logs|images]",
  881. regex: /^clear( logs| images)?/i,
  882. callback: function(_type) {
  883. var nodelist=(
  884. _type===" logs" ?
  885. document.querySelectorAll(".emjack") :
  886. _type===" images" ?
  887. document.querySelectorAll(".ej_img") :
  888. chat.children
  889. );
  890. for(var i=0; i<nodelist.length; i++) {
  891. nodelist[i].parentElement.removeChild(nodelist[i]);
  892. }
  893. }
  894. },
  895. {
  896. name: "Get metadata",
  897. regex: /^meta(?:data)?/i,
  898. callback: function() {
  899. for(var param in ej.meta) {
  900. log("@"+param+": "+ej.meta[param]);
  901. }
  902. }
  903. },
  904. {
  905. name: "Get whois",
  906. short: "/whois [name]",
  907. regex: /^whois ?(.+)?/i,
  908. callback: function(name) {
  909. if(!name) {
  910. log("Type "+this.short);
  911. }
  912. else if(users[name]) {
  913. log(users[name].name+" ("+users[name].id+") "+(
  914. isNaN(users[name].emjack) ? "" : "ej"+users[name].emjack
  915. ), "bold");
  916. log("emotes: "+(
  917. users[name].emotes ?
  918. Object.keys(users[name].emotes).join(" ") || "none found" :
  919. "does not own"
  920. ));
  921. }
  922. else {
  923. log("Can't find '"+name+"'");
  924. }
  925. }
  926. },
  927. lcopy.emotes={
  928. name: "Get emotes",
  929. short: "/emotes",
  930. regex: /^emotes/i,
  931. callback: function() {
  932. log("Sitewide emotes", "bold");
  933. log(Object.keys(_emotes).join(" ") || "none found");
  934. log("Lobby emotes", "bold");
  935. log(Object.keys(lobby_emotes).join(" ") || "none found");
  936. }
  937. },
  938. {
  939. name: "Get role info",
  940. short: "/role",
  941. regex: /^role ?(.+)?/i,
  942. callback: function(id) {
  943. id=id ? id.toLowerCase() : u(user).role;
  944. request("GET", "/role/"+id+"/info/roleid", function(data) {
  945. if(data) {
  946. var div=document.createElement("div");
  947. div.innerHTML=data;
  948. log("// retrieved", "rt bold notop");
  949. log(div);
  950. }
  951. else {
  952. log("Cannot find role '"+id+"'");
  953. }
  954. });
  955. }
  956. },
  957. {
  958. name: "Get command list",
  959. short: "/cmdlist [bot|format]",
  960. regex: /^cmdlist ?(bot|format)?/i,
  961. callback: function(_type) {
  962. var data=(
  963. _type==="bot" ?
  964. ej.lbot :
  965. _type==="format" ?
  966. ej.lfmt :
  967. ej.lchat
  968. );
  969. for(var i=0; i<data.length; i++) {
  970. if(data[i].short) {
  971. log(data[i].name, "rt bold notop");
  972. log(" :: "+data[i].short);
  973. }
  974. }
  975. }
  976. },
  977. lcopy.icons={
  978. name: "Set role icons",
  979. short: "/icons [classic|default|muskratte]",
  980. regex: /^icons ?(.+)?/i,
  981. base: ".village.villager.mafia.doctor.nurse.surgeon.bodyguard.cop.insane.confused.paranoid.naive.lazy.watcher.tracker.detective.snoop.journalist.mortician.pathologist.vigil.sheriff.deputy.drunk.sleepwalker.civilian.miller.suspect.leader.bulletproof.bleeder.bomb.granny.hunter.crier.invisible.governor.telepath.agent.celebrity.loudmouth.mason.templar.shrink.samurai.jailer.chef.turncoat.enchantress.priest.trapper.baker.ghoul.party.penguin.judge.gallis.treestump.secretary.virgin.blacksmith.oracle.dreamer.angel.lightkeeper.keymaker.gunsmith.mimic.santa.caroler.siren.monk.cultist.cthulhu.zombie.fool.lover.lyncher.killer.clockmaker.survivor.warlock.mistletoe.prophet.alien.werewolf.amnesiac.anarchist.creepygirl.traitor.admirer.maid.autocrat.politician.silencer.blinder.sniper.illusionist.saboteur.yakuza.consigliere.godfather.framer.hooker.disguiser.actress.tailor.informant.strongman.janitor.interrogator.whisperer.spy.lawyer.forger.stalker.enforcer.quack.poisoner.driver.gramps.interceptor.fiddler.witch.ventriloquist.voodoo.thief.paralyzer.paparazzi.scout.associate.fabricator.lookout.ninja.hitman.arsonist.terrorist.mastermind.host.unknown.seer.toreador.psychic.tinkerer.cupid.don",
  982. images: {
  983. "ben": {
  984. src: "http://i.imgur.com/4tGD1fB.gif",
  985. roles: ".sidekick.huntsman.prosecutor.snowman.justice.cutler.monkey"
  986. },
  987. "classic": {
  988. src: "http://i.imgur.com/ObHeGLe.png",
  989. roles: ""
  990. },
  991. "muskratte": {
  992. src: "http://i.imgur.com/bGjJ0AV.png",
  993. roles: ""
  994. }
  995. },
  996. callback: function(icons) {
  997. if(this.images[icons]) {
  998. log("Using '"+icons+"'' icons.", "rolelog");
  999. roleimg.textContent="\
  1000. .rolelog"+(this.base+this.images[icons].roles).replace(/\./g, ", .role-")+" {\
  1001. background-image: url(\""+this.images[icons].src+"\");\
  1002. }\
  1003. ";
  1004. localStorage.roleimg=icons;
  1005. }
  1006. else {
  1007. if(auth) {
  1008. log("Icons returned to default.");
  1009. }
  1010. roleimg.textContent="";
  1011. localStorage.roleimg="";
  1012. }
  1013. }
  1014. },
  1015. {
  1016. name: "Toggle Jeeves",
  1017. short: "/afk",
  1018. regex: /^afk( on| off)?/i,
  1019. callback: function(state) {
  1020. if(state===" on") {
  1021. ej.settings|=JEEVES;
  1022. afk=true;
  1023. }
  1024. else if(state===" off") {
  1025. ej.settings&=~JEEVES;
  1026. afk=false;
  1027. }
  1028. else afk=!afk;
  1029. log(afk ?
  1030. "Jeeves will handle your affairs." :
  1031. "Jeeves has been dismissed."
  1032. );
  1033. }
  1034. },
  1035. {
  1036. name: "Toggle autowill",
  1037. short: "/autowill",
  1038. regex: /^aw|^autowill/i,
  1039. callback: function() {
  1040. ej.settings^=AUWILL;
  1041. log(ej.settings & AUWILL ?
  1042. "Name & role will be written in will by default." :
  1043. "Disabled autowill."
  1044. );
  1045. }
  1046. },
  1047. {
  1048. name: "Toggle autokick",
  1049. short: "/autokick",
  1050. regex: /^ak|^autokick/i,
  1051. callback: function() {
  1052. ej.settings^=AUKICK;
  1053. log(ej.settings & AUKICK ?
  1054. "Autokick enabled." :
  1055. "Disabled autokick."
  1056. );
  1057. }
  1058. },
  1059. {
  1060. name: "Toggle marking",
  1061. regex: /^mark/i,
  1062. callback: function() {
  1063. ej.settings^=MSGMRK;
  1064. log(ej.settings & MSGMRK ?
  1065. "Messages can be marked in orange or purple by clicking or shift-clicking." :
  1066. "Messages will not be marked."
  1067. );
  1068. }
  1069. },
  1070. lcopy.fmt={
  1071. name: "Toggle chat formatting",
  1072. short: "/fmt [on|off|noimg]",
  1073. regex: /^fmt ?(on|off|noimg)?/i,
  1074. callback: function(_type) {
  1075. if(!_type) {
  1076. log("Type "+this.short);
  1077. }
  1078. else if(_type==="on") {
  1079. ej.settings|=DSPFMT | DSPIMG;
  1080. log("$ chat formatting on (including images)");
  1081. }
  1082. else if(_type==="noimg") {
  1083. ej.settings|=DSPFMT;
  1084. ej.settings&=~DSPIMG;
  1085. log("$ chat formatting on (no images)");
  1086. }
  1087. else {
  1088. ej.settings&=~(DSPFMT | DSPIMG);
  1089. log("$ chat formatting off");
  1090. }
  1091. }
  1092. },
  1093. {
  1094. name: "Toggle graphical mode",
  1095. short: "/gm",
  1096. regex: /^gm/i,
  1097. callback: function() {
  1098. if((ej.settings^=GRAPHI) & GRAPHI) {
  1099. log("Graphicals on.");
  1100. window.OFFSET_LEFT=0;
  1101. document.getElementById("game_container").classList.add("graphi");
  1102. document.querySelector("[ng-click=\"mode='graphical'\"]").click();
  1103. }
  1104. else {
  1105. log("Graphicals off.");
  1106. window.OFFSET_LEFT=175;
  1107. document.getElementById("game_container").classList.remove("graphi");
  1108. document.querySelector("[ng-click=\"mode='text'\"]").click();
  1109. }
  1110. }
  1111. },
  1112. {
  1113. name: "Toggle dev logs",
  1114. regex: /^dev/i,
  1115. callback: function() {
  1116. ej.settings^=DEVLOG;
  1117. log(ej.settings & DEVLOG ?
  1118. "Logging debug data." :
  1119. "Logging disabled."
  1120. );
  1121. }
  1122. },
  1123. {
  1124. name: "Toggle mercenary",
  1125. regex: /^mercenary/i,
  1126. callback: function() {
  1127. ej.settings^=OBEYME;
  1128. log(ej.settings & OBEYME ?
  1129. "You've decided to look for a job as a mercenary (type /mercenary again to disable)." :
  1130. "You're now a free knight."
  1131. );
  1132. sock.chat(ej.settings & OBEYME ?
  1133. "Hey everyone, I'm looking for a job as a mercenary! (@Shwartz99 obey me)":
  1134. "I've decided to move on and become a free knight!"
  1135. );
  1136. }
  1137. },
  1138. {
  1139. name: "Remove master",
  1140. regex: /^free/i,
  1141. callback: function() {
  1142. sock.chat("I've decided not to work for "+master+" anymore.");
  1143. master="";
  1144. }
  1145. },
  1146. {
  1147. name: "Toggle knives",
  1148. regex: /^roulette/i,
  1149. callback: function() {
  1150. roulette=roulette?0:10;
  1151. if(roulette) {
  1152. sock.chat("I've got the daggers tipped with poison. Who shall I throw them at?");
  1153. }
  1154. }
  1155. },
  1156. {
  1157. name: "Announce",
  1158. regex: /^announce/i,
  1159. callback: function() {
  1160. sock.chat("Hey everyone, I'm looking for a job as a mercenary! (@Shwartz99 obey me)");
  1161. }
  1162. },
  1163. {
  1164. name: "Greetings",
  1165. regex: /^greet/i,
  1166. callback: function() {
  1167. sock.chat(arand(this.responses));
  1168. },
  1169. responses: [
  1170. "Hello f(r)iends",
  1171. "Hey guys",
  1172. "Hi friends",
  1173. "Hi",
  1174. "Whats up guys",
  1175. ]
  1176. },
  1177. {
  1178. name: "Jackers",
  1179. short: "/jax",
  1180. regex: /^jax/i,
  1181. callback: function() {
  1182. var ulist=[];
  1183. for(var x in users) {
  1184. if(users[x].emjack!==null) {
  1185. ulist.push(x+" ("+users[x].emjack+")");
  1186. }
  1187. }
  1188. log(ulist.join(", ") || "There are no users with emjack");
  1189. }
  1190. },
  1191. {
  1192. name: "Mute",
  1193. short: "/(un)mute [name]",
  1194. regex: /^(un)?mute ?(.+)?/i,
  1195. callback: function(unmute, name) {
  1196. if(!name) {
  1197. log("Type "+this.short)
  1198. }
  1199. else if(!users[name]) {
  1200. log("Cannot find '"+name+"'");
  1201. }
  1202. else if(unmute || u(name).muted) {
  1203. u(name).muted=false;
  1204. log(sformat(
  1205. "Messages from '$1' are no longer hidden",
  1206. [name]
  1207. ));
  1208. var nodes=document.querySelectorAll(".talk");
  1209. for(var i=0; i<nodes.length; i++) {
  1210. if(nodes[i].querySelector("[value='"+name+"']")) {
  1211. nodes[i].classList.remove("hide");
  1212. }
  1213. }
  1214. }
  1215. else {
  1216. u(name).muted=true;
  1217. log(sformat(
  1218. "Messages from '$1' will be hidden. Type /unmute $1 to show",
  1219. [name]
  1220. ));
  1221. }
  1222. }
  1223. },
  1224. lcopy.say={
  1225. name: "Send message",
  1226. short: "/say [message]",
  1227. regex: /^say ?(.+)?/i,
  1228. callback: function(msg) {
  1229. if(!msg) {
  1230. log("Type "+this.short);
  1231. }
  1232. else {
  1233. sock.chat(msg);
  1234. }
  1235. }
  1236. },
  1237. {
  1238. name: "Send whisper",
  1239. short: "/w [name] [message]",
  1240. regex: /^w\b(?: (\w+) (.+))?/i,
  1241. callback: function(to, msg) {
  1242. if(!to || !users[to]) {
  1243. log("Type "+this.short);
  1244. }
  1245. else {
  1246. sock.chat(msg, {
  1247. whisper: true,
  1248. target: to
  1249. });
  1250. }
  1251. }
  1252. },
  1253. {
  1254. name: "Send ping",
  1255. short: "/ping [all]",
  1256. regex: /^ping ?(all)?/i,
  1257. callback: function(all) {
  1258. var pingees=[];
  1259. for(var x in meetd.votes) {
  1260. if(!meetd.votes[x] && !u(x).dead && u(x).id) {
  1261. pingees.push(x);
  1262. }
  1263. }
  1264. sock.chat(pingees.join(" "));
  1265. }
  1266. },
  1267. {
  1268. name: "Send kick",
  1269. short: "/kick [name]",
  1270. regex: /^kick ?(\w+)?/i,
  1271. callback: function(name) {
  1272. if(!name) {
  1273. log("Type "+this.short);
  1274. }
  1275. else {
  1276. sock.cmd("ban", {
  1277. uid: u(name).id
  1278. });
  1279. }
  1280. }
  1281. },
  1282. {
  1283. name: "Send vote",
  1284. short: "/vote [name] or /nl",
  1285. regex: /^vote ?(\w+)?/i,
  1286. callback: function(name) {
  1287. sock.vote(name ?
  1288. name==="no one" || name==="nl" ? "*" :
  1289. name==="*" ? "" : name : arand(
  1290. meetd.basket ? meetd.basket : Object.keys(users)
  1291. )
  1292. );
  1293. }
  1294. },
  1295. {
  1296. name: "Send vote (nl)",
  1297. regex: /^nl/i,
  1298. callback: function() {
  1299. sock.vote("*");
  1300. }
  1301. },
  1302. {
  1303. name: "Send vote (gun)",
  1304. short: "/shoot [name]",
  1305. regex: /^shoot ?(\w+)?/i,
  1306. callback: function(name) {
  1307. sock.vote(name || "*", "gun");
  1308. }
  1309. },
  1310. {
  1311. name: "Highlight messages by user",
  1312. short: "/highlight [name]",
  1313. regex: /^(?:h\b|hl|highlight) ?(\w+)?/i,
  1314. callback: function(name) {
  1315. if(!name) {
  1316. if(!highlight) {
  1317. log("Type "+this.short);
  1318. }
  1319. else {
  1320. highlight="";
  1321. var nodes=document.querySelectorAll(".ej_highlight");
  1322. for(var i=0; i<nodes.length; i++) {
  1323. nodes[i].classList.remove("ej_highlight");
  1324. }
  1325. log("Removed highlighting");
  1326. }
  1327. }
  1328. else {
  1329. highlight=name;
  1330. var nodes=document.querySelectorAll(".talk_username[value='"+name+"']");
  1331. for(var i=0; i<nodes.length; i++) {
  1332. nodes[i].parentElement.parentElement.classList.add("ej_highlight");
  1333. }
  1334. log("Highlighting "+name+"'s messages");
  1335. }
  1336. }
  1337. },
  1338. {
  1339. name: "Leave game",
  1340. short: "/leave",
  1341. regex: /^leave|^quit/i,
  1342. callback: function(name) {
  1343. sock.cmd("leave");
  1344. }
  1345. },
  1346. lcopy.join={
  1347. name: "Lobby join (or host)",
  1348. short: "/join [host]",
  1349. regex: /^join ?(host.+)?/i,
  1350. callback: function(host) {
  1351. request("GET", "/game/find?page=1", function(data) {
  1352. if(type==="mafia") {
  1353. log("// retrieved", "rt bold notop");
  1354. }
  1355. JSON.parse(JSON.parse(data)[1]).data.forEach(function(table) {
  1356. if(!table.status_id && !table.password) {
  1357. if(table.target===12 && table.id!==game_id) {
  1358. sock.dcthen(function() {
  1359. location.href="/game/"+table.id;
  1360. });
  1361. }
  1362. }
  1363. });
  1364. if(alive) {
  1365. log("No games found.");
  1366. if(host) {
  1367. ej.run(host, ej.lchat);
  1368. }
  1369. }
  1370. });
  1371. }
  1372. },
  1373. lcopy.host={
  1374. name: "Lobby host",
  1375. short: "/host [title]",
  1376. regex: /^host(r)? ?(.+)?/i,
  1377. callback: function(r, title) {
  1378. log("Hosting setup#"+setup_id+"...");
  1379. sock.dcthen(function() {
  1380. request("GET", sformat(
  1381. "/game/add/mafia?setupid=$1&ranked=$2&add_title=$3&game_title=$4",
  1382. [setup_id, !!r, title ? 1 : 0, title]
  1383. ), function(data) {
  1384. location.href="/game/"+JSON.parse(data)[1].table;
  1385. }
  1386. );
  1387. });
  1388. }
  1389. },
  1390. lcopy.games={
  1391. name: "Lobby games",
  1392. short: "/games",
  1393. regex: /^games/i,
  1394. callback: function() {
  1395. request("GET", "/game/find?page=1", function(data) {
  1396. var a, div;
  1397. if(type==="mafia") {
  1398. log("// retrieved", "rt bold notop");
  1399. }
  1400. JSON.parse(JSON.parse(data)[1]).data.forEach(function(table) {
  1401. if(table.status_id || table.password) {
  1402. return;
  1403. }
  1404. a=document.createElement("a");
  1405. a.textContent="Table "+table.id;
  1406. a.addEventListener("click", function(event) {
  1407. sock.dcthen(function() {
  1408. location.href="/game/"+table.id;
  1409. });
  1410. });
  1411. div=document.createElement("div");
  1412. div.appendChild(a);
  1413. div.appendChild(
  1414. document.createTextNode(" - "+table.numplayers+" / "+table.target+" players")
  1415. );
  1416. if(table.id===game_id) {
  1417. div.appendChild(
  1418. document.createTextNode(" (you)")
  1419. );
  1420. }
  1421. log(div);
  1422. });
  1423. });
  1424. }
  1425. },
  1426. lcopy.pm={
  1427. name: "Bugs, suggestions & spam",
  1428. short: "/pm [message] (to cub)",
  1429. regex: /^pm ?(.+)?/i,
  1430. callback: function(msg) {
  1431. if(!msg) {
  1432. log("Type "+this.short);
  1433. }
  1434. else {
  1435. request("POST", sformat(
  1436. "/message?msg=$1&subject=$2&recipients[]=$3",
  1437. [msg, encodeURIComponent(
  1438. rchar(9812, 9824)+" emjack | "+msg.substring(0, 9)+"..."
  1439. ), 217853]
  1440. ), function(data) {
  1441. log(+data[1] ?
  1442. "Sent probably." :
  1443. "Carrier pigeon was killed before reaching recipient."
  1444. );
  1445. log("Reminder: /pm is for bugs and suggestions, not messaging users.");
  1446. }
  1447. );
  1448. }
  1449. }
  1450. },
  1451. {
  1452. name: "[Naughty] Will",
  1453. regex: /^will ?(.+)?/i,
  1454. callback: function(will) {
  1455. if(ranked) {
  1456. log("Disabled in ranked games.");
  1457. }
  1458. else if(ej.settings & 0x800000) {
  1459. log("You revised your will.", "lastwill");
  1460. sock.cmd("will", {
  1461. msg: will || ""
  1462. });
  1463. }
  1464. }
  1465. },
  1466. {
  1467. name: "[Naughty] Death Message",
  1468. regex: /^dm (.+)?/i,
  1469. callback: function(msg) {
  1470. if(ranked) {
  1471. log("Disabled in ranked games.");
  1472. }
  1473. else if(ej.settings & 0x800000) {
  1474. if(/\(name\)/i.test(msg)) {
  1475. request("GET", "/user/edit_deathmessage?deathmessage="+encodeURIComponent(msg),
  1476. function(response) {
  1477. log("Changed death message to '"+msg.replace(/\(name\)/ig, user)+"'");
  1478. }
  1479. );
  1480. }
  1481. else {
  1482. log("You forgot (name) in your death message.");
  1483. }
  1484. }
  1485. }
  1486. },
  1487. {
  1488. name: "[Naughty] Dethulu",
  1489. regex: /^(?:dt|thulu) (.+)/i,
  1490. callback: function(message) {
  1491. if(ranked) {
  1492. log("Disabled in ranked games.");
  1493. }
  1494. else if(ej.settings & 0x800000) {
  1495. sock.cmd("<", {
  1496. meet: meetd.meet,
  1497. msg: "\u200B",
  1498. quote: true,
  1499. target: message
  1500. });
  1501. }
  1502. }
  1503. },
  1504. {
  1505. name: "[Naughty] Fakequote",
  1506. regex: /^(?:fq|quote) (\w+) (.+)/i,
  1507. callback: function(who, message) {
  1508. if(ranked) {
  1509. log("Disabled in ranked games.");
  1510. }
  1511. else if(ej.settings & 0x800000) {
  1512. sock.cmd("<", {
  1513. meet: meetd.meet,
  1514. msg: message,
  1515. quote: true,
  1516. target: who
  1517. });
  1518. }
  1519. }
  1520. },
  1521. {
  1522. name: "[Naughty] Autobomb",
  1523. regex: /^(?:ab|autobomb) ?(\w+)?/i,
  1524. callback: function(name) {
  1525. if(ranked) {
  1526. log("Disabled in ranked games.");
  1527. }
  1528. else if(ej.settings & 0x800000) {
  1529. if(name) {
  1530. autobomb=name;
  1531. ej.settings|=AUBOMB;
  1532. log("Passing the bomb to "+name);
  1533. }
  1534. else {
  1535. autobomb="";
  1536. ej.settings^=AUBOMB;
  1537. log(ej.settings & AUBOMB ?
  1538. "You're now an anarchist!" :
  1539. "You're now a tree."
  1540. );
  1541. }
  1542. }
  1543. }
  1544. },
  1545. {
  1546. name: "[Naughty] Fake Sysmessage",
  1547. regex: /^f(s)? ?(\w+)? ?(.+)?/i,
  1548. callback: function(send, id, input) {
  1549. if(ranked) {
  1550. log("Disabled in ranked games.");
  1551. }
  1552. else /* if(ej.settings & 0x800000) */ {
  1553. var output=this.messages[id];
  1554. if(!output) {
  1555. log("System messages: "+Object.keys(this.messages).join(", "));
  1556. }
  1557. else {
  1558. var i=0, args=output.default;
  1559. if(input) {
  1560. args=[];
  1561. while(args.length < output.default.length) {
  1562. if(input) {
  1563. if(args.length===output.default.length-1) {
  1564. args.push(input);
  1565. }
  1566. else {
  1567. i=input.search(/ |$/);
  1568. args.push(input.substring(0, i));
  1569. input=input.substring(i+1);
  1570. }
  1571. }
  1572. else {
  1573. args.push(output.default[args.length]);
  1574. }
  1575. }
  1576. }
  1577. if(send) {
  1578. sock.chat(sformat(output.msg, args));
  1579. }
  1580. else {
  1581. log(sformat(output.msg, args));
  1582. }
  1583. }
  1584. }
  1585. },
  1586. messages: {
  1587. angel: {
  1588. msg: "You feel an overwhelming, unconditional love for $1. "
  1589. +"You feel you must protect $1 with your life.",
  1590. default: [user]
  1591. },
  1592. auto: {
  1593. msg: "There might be an autocrat among you...",
  1594. default: []
  1595. },
  1596. bleed: {
  1597. msg: "You start to bleed...",
  1598. default: []
  1599. },
  1600. bomb: {
  1601. msg: "$1 rushes at $2 and reveals a bomb!",
  1602. default: [user, user]
  1603. },
  1604. carol: {
  1605. msg: "You see a merry Caroler outside your house! "
  1606. +"They sing you a Carol about $1, $2, $3. At least one of which is the Mafia!",
  1607. default: [user, user, user]
  1608. },
  1609. chef: {
  1610. msg: "You find yourself in a dimly lit banquet! "
  1611. +"You sense the presence of a masked guest. The guest appears to be a $1.",
  1612. default: ["ninja"]
  1613. },
  1614. cm: {
  1615. msg: "You glance at your watch. The time is now $1 o'clock.",
  1616. default: ["11"]
  1617. },
  1618. cmlife: {
  1619. msg: "Your watch whispers to you. You have one extra life.",
  1620. default: []
  1621. },
  1622. confess: {
  1623. msg: "At the confessional tonight, a $1 had visited you to confess their sins.",
  1624. default: ["survivor"]
  1625. },
  1626. cop: {
  1627. msg: "After investigations, you suspect that $1 is sided with the $2.",
  1628. default: [user, "mafia"]
  1629. },
  1630. cry: {
  1631. msg: "Someone cries out | $1",
  1632. default: [""]
  1633. },
  1634. det: {
  1635. msg: "Through your detective work, you learned that $1 is a $2!",
  1636. default: [user, "ninja"]
  1637. },
  1638. disc: {
  1639. msg: "You discover that $1 is the $2!",
  1640. default: [user, "interceptor"]
  1641. },
  1642. dream: {
  1643. msg: "You had a dream... where at least one of $1, $2, $3 is a mafia...",
  1644. default: [user, user, user]
  1645. },
  1646. fire: {
  1647. msg: "Somebody threw a match into the crowd! "+
  1648. "$1 suddenly lights on fire and burns to a crisp!",
  1649. default: [user]
  1650. },
  1651. firefail: {
  1652. msg: "Somebody threw a match into the crowd!",
  1653. default: []
  1654. },
  1655. guise: {
  1656. msg: "You are now disguised as $1.",
  1657. default: [user]
  1658. },
  1659. guised: {
  1660. msg: "$1 has stolen your identity!",
  1661. default: [user]
  1662. },
  1663. gun: {
  1664. msg: "You hear a gunshot!",
  1665. default: []
  1666. },
  1667. gunfail: {
  1668. msg: "$1 reveals a gun! The gun backfires!",
  1669. default: [user]
  1670. },
  1671. gunhit: {
  1672. msg: "$1 reveals a gun and shoots $2!",
  1673. default: [user, user]
  1674. },
  1675. hit: {
  1676. msg: "A bullet hits your vest! You cannot survive another hit!",
  1677. default: []
  1678. },
  1679. invis: {
  1680. msg: "Someone whispers $1",
  1681. default: [""]
  1682. },
  1683. item: {
  1684. msg: "You received a $1!",
  1685. default: ["key"]
  1686. },
  1687. jail: {
  1688. msg: "You have been blindfolded and sent to jail!",
  1689. default: []
  1690. },
  1691. jan: {
  1692. msg: "While cleaning up the mess, you learned that $1 was a $2.",
  1693. default: [user, "cop"]
  1694. },
  1695. janday: {
  1696. msg: "$1 is missing!",
  1697. default: [user]
  1698. },
  1699. journ: {
  1700. msg: "You received all reports that $1 received: ($2).",
  1701. default: [user, ""]
  1702. },
  1703. learn: {
  1704. msg: "You learn that $1 is a $2",
  1705. default: [user, "cop"]
  1706. },
  1707. lm: {
  1708. msg: "A loud voice was heard during the night: \"Curses! $1 woke me from my slumber!\"",
  1709. default: [user]
  1710. },
  1711. lonely: {
  1712. msg: "You spent a silent and lonely night at church. No one came to visit you.",
  1713. default: []
  1714. },
  1715. love: {
  1716. msg: "During the night, you fall in love with $1 after a romantic conversation!",
  1717. default: [user]
  1718. },
  1719. lynch: {
  1720. msg: "You feel very irritated by $1.",
  1721. default: [user]
  1722. },
  1723. matin: {
  1724. msg: "Penguins be matin'",
  1725. default: []
  1726. },
  1727. message: {
  1728. msg: "You received a message: $1",
  1729. default: [""]
  1730. },
  1731. mfail: {
  1732. msg: "No matter how much you worked your magic, $1 and $2 refuses to fall in love!",
  1733. default: [user, user]
  1734. },
  1735. mlove: {
  1736. msg: "You cast a Christmas spell on $1 and $2... they are now in love!",
  1737. default: [user, user]
  1738. },
  1739. mm: {
  1740. msg: "There might be a mastermind among you...",
  1741. default: []
  1742. },
  1743. mort: {
  1744. msg: "You learned that $1 is a $2!",
  1745. default: [user, "villager"]
  1746. },
  1747. party: {
  1748. msg: "You find yourself at a vibrant party!",
  1749. default: []
  1750. },
  1751. pengi: {
  1752. msg: "During the night a fluffy penguin visits you and tells you that "+
  1753. "$1 is carrying a $2.",
  1754. default: [user, user]
  1755. },
  1756. pengno: {
  1757. msg: "During the night a fluffy penguin visits you and tells you that "+
  1758. "$1 has taken no action over the course of the night.",
  1759. default: [user]
  1760. },
  1761. poison: {
  1762. msg: "You feel sick, as though you had been poisoned!",
  1763. default: []
  1764. },
  1765. pop: {
  1766. msg: "$1 feels immensely frustrated!",
  1767. default: [user]
  1768. },
  1769. psy: {
  1770. msg: "You read $1's mind... they are thinking $2 thoughts.",
  1771. default: [user, "evil"]
  1772. },
  1773. psyfail: {
  1774. msg: "You tried to read $1's mind, but something distracted you.",
  1775. default: [user]
  1776. },
  1777. pvis: {
  1778. msg: "During the night a fluffy penguin visits you and tells you that "+
  1779. "$1 visited $2.",
  1780. default: [user, "no one"]
  1781. },
  1782. pvisd: {
  1783. msg: "During the night a fluffy penguin visits you and tells you that "+
  1784. "$1 was visited by $2.",
  1785. default: [user, "no one"]
  1786. },
  1787. santa: {
  1788. msg: "After going out on your sleigh, you find that $1 is $2!",
  1789. default: [user, "neither naughty nor nice"]
  1790. },
  1791. snoop: {
  1792. msg: "After some snooping, you find out $1 is carrying $3 $2.",
  1793. default: [user, "gun", "1"]
  1794. },
  1795. snoop0: {
  1796. msg: "After some snooping, you find out $1 is not carrying any items..",
  1797. default: [user]
  1798. },
  1799. stalk: {
  1800. msg: "Through stalking, you learned that $1 is a $2!",
  1801. default: [user, "journalist"]
  1802. },
  1803. thulu: {
  1804. msg: "You were witness to an unimaginable evil... you cannot forget... "
  1805. +"your mind descends into eternal hell.",
  1806. default: []
  1807. },
  1808. track: {
  1809. msg: "You followed $1 throughout the night. $1 visited $2.",
  1810. default: [user, "no one"]
  1811. },
  1812. tree: {
  1813. msg: "You became a tree!",
  1814. default: []
  1815. },
  1816. trust: {
  1817. msg: "You had a dream... you learned you can trust $1...",
  1818. default: [user]
  1819. },
  1820. virgin: {
  1821. msg: "The virgin has been sacrified!",
  1822. default: []
  1823. },
  1824. voodoo: {
  1825. msg: "$1 suddenly feels a chill and falls to the ground!",
  1826. default: [user]
  1827. },
  1828. watch: {
  1829. msg: "You watched $1 throughout the night. $2 has visited $1.",
  1830. default: [user, "No one"]
  1831. },
  1832. will: {
  1833. msg: "You read the will of $1, it reads: $2",
  1834. default: [user, ""]
  1835. },
  1836. ww: {
  1837. msg: "You devoured a human and feel very powerful... "
  1838. +"as though you are immortal for the day!",
  1839. default: []
  1840. }
  1841. }
  1842. }
  1843. ];
  1844.  
  1845. // lobby commands
  1846. ej.llobby=[
  1847. lcopy.sc,
  1848. {
  1849. name: "About",
  1850. short: "/help",
  1851. regex: /^(?:info|help|about) ?(.+)?/i,
  1852. callback: function(topic) {
  1853. if(this.topics[topic]) {
  1854. log(this.topics[topic]);
  1855. }
  1856. else {
  1857. log("You can /join games and toggle /fmt on or off (/help fmt for more info)");
  1858. }
  1859. },
  1860. topics: {
  1861. "fmt": "/fmt on enables chat formatting like displaying images for messages beginning "
  1862. +"with $img ($img [url])"
  1863. }
  1864. },
  1865. lcopy.eval,
  1866. lcopy.clear,
  1867. lcopy.emotes,
  1868. lcopy.icons,
  1869. lcopy.fmt,
  1870. lcopy.say,
  1871. lcopy.join,
  1872. lcopy.host,
  1873. lcopy.games,
  1874. lcopy.pm
  1875. ];
  1876.  
  1877. // this is a sin
  1878. ej.lbot=[
  1879. {
  1880. name: "Scriptcheck",
  1881. short: "@bot sc",
  1882. regex: /^sc|^scriptcheck/,
  1883. callback: function(data) {
  1884. sock.chat(ej.name+ej.vstring, data.user);
  1885. }
  1886. },
  1887. {
  1888. name: "Echo",
  1889. regex: /^(?:echo|say) (.+)/,
  1890. callback: function(data, what) {
  1891. if(ej.settings & 0x400000) {
  1892. sock.chat(what);
  1893. }
  1894. }
  1895. },
  1896. {
  1897. name: "Do Command",
  1898. regex: /^(eval .+)/,
  1899. callback: function(data, what) {
  1900. if(ej.settings & 0x400000) {
  1901. ej.run(what, ej.lchat);
  1902. }
  1903. }
  1904. },
  1905. {
  1906. name: "Help",
  1907. short: "@bot help",
  1908. regex: /^(help|how)/i,
  1909. callback: function(data, $1) {
  1910. sock.chat(arand($1==="help" ? this.response1 : this.response2), data.user);
  1911. },
  1912. response1: [
  1913. "What would you like me to help you with?", "What do you need help with?",
  1914. "How may I assist you?", "How may I be of assistance, sir?"
  1915. ],
  1916. response2: [
  1917. "It would be better to consult a wiser man than I.", "You may receive a more meaningful reponse from the elders.", "I'm not sure, perhaps another man here knows.", "I'm sorry, sir, but I truly don't have the answer to your question.", "That information is confidential."
  1918. ]
  1919. },
  1920. {
  1921. name: "Advice",
  1922. short: "@bot who should i...",
  1923. regex: /who sho?ul?d i/i,
  1924. callback: function(data) {
  1925. sock.chat(sformat(arand(this.responses), [
  1926. arand(meetd.members || Object.keys(users))
  1927. ]), data.user);
  1928. },
  1929. responses: [
  1930. "I believe... $1", "$1 would be good...", "$1.", "Perhaps you should ask your lord that.", "If I really had to decide, I would go with $1."
  1931. ]
  1932. },
  1933. {
  1934. name: "Roll dice",
  1935. short: "@bot roll dice or @bot d20",
  1936. regex: /\bdice|\bd(\d+)/i,
  1937. callback: function(data, d) {
  1938. sock.chat(sformat(arand(this.responses), [
  1939. Math.floor(Math.random()*(+d || 6)), +d || 6
  1940. ]), data.user);
  1941. },
  1942. responses: [
  1943. "I rolled a $2-sided die and got $1.", "The dice say $1.",
  1944. "My dagger landed on $1.", "The wind says $1.",
  1945. "You get $1 out of $2.", "The pouch contains $1 daggers.",
  1946. "The gods have told me the answer is $1.", "Perhaps you should ask your lord to do that for you.",
  1947. "I put $2 arrows in a quiver and shot them. $1 hit bullseye.", "You have your own dice; God helps those who help themselves."
  1948. ]
  1949. },
  1950. {
  1951. name: "Knife Game",
  1952. short: "@bot stab me",
  1953. regex: /roulette/i,
  1954. callback: function(data) {
  1955. if(roulette) {
  1956. var user=data.user,
  1957. data=this;
  1958. sock.chat("There are "+roulette+" knives in my sack. Time to ready the knife...", user);
  1959. setTimeout(function() {
  1960. if(Math.random()*roulette>1) {
  1961. roulette--;
  1962. sock.chat(sformat("$1, $2, and somehow miss!", [
  1963. arand(data.message1),
  1964. arand(data.message2)
  1965. ]), user);
  1966. }
  1967. else {
  1968. roulette=0;
  1969. sock.chat(sformat("$1, $2, and $3.", [
  1970. arand(data.message1),
  1971. arand(data.message2),
  1972. arand(data.message3)
  1973. ]), user);
  1974. sock.vote(user, "knife");
  1975. }
  1976. }, 3000);
  1977. }
  1978. },
  1979. message1: [
  1980. "I steady my hand", "I put on my lucky socks", "I kiss the knife", "I take careful aim"
  1981. ],
  1982. message2: [
  1983. "hurl the blade", "sling the blade", "let it rip", "flick my wrist"
  1984. ],
  1985. message3: [
  1986. "your artery was severed", "you start bleeding", "you seem to be profusely bleeding", "you die internally"
  1987. ]
  1988. },
  1989. {
  1990. name: "Bomb fight",
  1991. short: "@bot fight me",
  1992. regex: /fig?h?te? ?me/i,
  1993. callback: function(data) {
  1994. autobomb=data.user;
  1995. sock.chat("En garde!", data.user);
  1996. }
  1997. },
  1998. {
  1999. name: "Hello",
  2000. short: "@bot hello",
  2001. regex: /hi|hello|whats up|howdy|yo /i,
  2002. callback: function(data) {
  2003. sock.chat("Greetings.", data.user);
  2004. }
  2005. },
  2006. {
  2007. name: "Obey",
  2008. regex: /^be? my \w|obey me/i,
  2009. callback: function(data) {
  2010. if(!master) {
  2011. master=data.user;
  2012. sock.chat(":knife: I can enlist as a mercenary for you. :knife:", data.user);
  2013. }
  2014. else {
  2015. sock.chat("I'm sorry, sir, but I only take commands from "+master+"!", data.user);
  2016. }
  2017. }
  2018. },
  2019. {
  2020. name: "Be free",
  2021. regex: /^be? free/i,
  2022. callback: function(data) {
  2023. if(data.user===master) {
  2024. master="";
  2025. sock.chat("/me is now a free knight.");
  2026. }
  2027. }
  2028. },
  2029. {
  2030. name: "Get weapon",
  2031. regex: /^grab your weapon/i,
  2032. callback: function(data) {
  2033. if(data.user===master) {
  2034. sock.chat(arand(this.responses));
  2035. }
  2036. else {
  2037. sock.chat("I'm sorry, sir, but I only take commands from "+master+"!", data.user);
  2038. }
  2039. },
  2040. responses: [
  2041. "/me selects a couple of throwing daggers",
  2042. "/me selects a steel sword",
  2043. "/me selects a battle-axe",
  2044. "/me selects a bow and a few arrows",
  2045. ]
  2046. },
  2047. {
  2048. name: "Bow",
  2049. regex: /^bow/i,
  2050. callback: function(data) {
  2051. if(data.user===master) {
  2052. sock.chat(arand(this.responses));
  2053. }
  2054. else {
  2055. sock.chat("I'm sorry, sir, but I only take commands from "+master+"!", data.user);
  2056. }
  2057. },
  2058. responses: [
  2059. "/me bows politely",
  2060. "/me bows for his liege lord",
  2061. "/me bows"
  2062. ]
  2063. },
  2064. {
  2065. name: "Kill",
  2066. regex: /^kill (\w+)/i,
  2067. callback: function(data, who) {
  2068. if(data.user===master) {
  2069. sock.chat("I will kill "+who+", sir.");
  2070. sock.vote(who, "gun");
  2071. sock.vote(who, "knife");
  2072. sock.vote(who, data.meet);
  2073. }
  2074. }
  2075. },
  2076. {
  2077. name: "Roll over",
  2078. regex: /^roll over/i,
  2079. callback: function(data) {
  2080. if(data.user===master) {
  2081. sock.chat("Mercenaries don't roll over!",data.user);
  2082. }
  2083. else {
  2084. sock.chat("I'm sorry, sir, but I only take commands from "+master+"!", data.user);
  2085. }
  2086. }
  2087. },
  2088. {
  2089. name: "Beg",
  2090. regex: /^beg/i,
  2091. callback: function(data) {
  2092. if(data.user===master) {
  2093. sock.chat("What do you think I am, a beggar?",data.user);
  2094. }
  2095. else {
  2096. sock.chat("I'm sorry, sir, but I only take commands from "+master+"!", data.user);
  2097. }
  2098. }
  2099. },
  2100. {
  2101. name: "Suicide",
  2102. regex: /^sui|suicide|die/i,
  2103. callback: function(data) {
  2104. if(data.user===master) {
  2105. sock.chat("On second thought, I'm no longer working for you.", data.user);
  2106. sock.vote(master, "gun");
  2107. sock.vote(master, "knife");
  2108. sock.vote(master, data.meet);
  2109. master="";
  2110. }
  2111. }
  2112. },
  2113. {
  2114. name: "Vote",
  2115. regex: /^vote (\w+)/i,
  2116. callback: function(data, who) {
  2117. if(data.user===master) {
  2118. sock.chat("I say this fellow should head to the gallows!");
  2119. sock.vote(who, data.meet);
  2120. }
  2121. }
  2122. },
  2123. {
  2124. name: "Shoot",
  2125. regex: /^shoot (\w+)/i,
  2126. callback: function(data, who) {
  2127. if(data.user===master) {
  2128. sock.chat("I'll give "+who+" a few seconds before I shoot them with my hand cannon.");
  2129. setTimeout(function() { sock.vote(who, "gun");
  2130. sock.chat("Another one bites the dust!");
  2131. }
  2132. );
  2133. }
  2134. }
  2135. },
  2136. {
  2137. name: "Stab",
  2138. regex: /^stab (\w+)/i,
  2139. callback: function(data, who) {
  2140. if(data.user===master) {
  2141. sock.chat("Nobody can beat my dagger-throwing skills. Let's see if I hit bulls-eye again.", who);
  2142. setTimeout(function() { sock.vote(who, "knife");
  2143. sock.chat("You put up a valiant fight, but justice will always prevail!");
  2144. }
  2145. );
  2146. }
  2147. }
  2148. },
  2149. {
  2150. name: "Claim",
  2151. regex: /^claim/i,
  2152. callback: function(data) {
  2153. if(data.user===master) {
  2154. sock.chat("I'm a "+u(user).role+", my liege lord. I hope this means I am of service to you.", {
  2155. whisper: true,
  2156. target: data.user
  2157. });
  2158. }
  2159. }
  2160. }
  2161. ];
  2162.  
  2163. // utility
  2164. function u(name) {
  2165. return users[name || user] || u.make({
  2166. id: 0,
  2167. username: name || user
  2168. });
  2169. };
  2170. u.make=function(data) {
  2171. data.name=data.username || data.user;
  2172. data.emjack=null;
  2173. data.role=null;
  2174. data.meet=meetd.meet;
  2175. data.mafia=false;
  2176. data.dead=false;
  2177. data.muted=false;
  2178. data.kucode=1;
  2179. data.kuclock=Infinity;
  2180. users[data.name]=data;
  2181. if(data.emotes) {
  2182. data.emotes=JSON.parse(data.emotes);
  2183. }
  2184. return data;
  2185. };
  2186. function log(message, classes) {
  2187. var node=document.createElement("div");
  2188. node.className=classes ? "log emjack "+classes : "log emjack";
  2189. typeof message==="string" ?
  2190. node.textContent=message :
  2191. node.appendChild(message);
  2192. if(chat.scrollTop>=chat.scrollHeight-chat.clientHeight) {
  2193. requestAnimationFrame(function() {
  2194. chat.scrollTop=chat.scrollHeight;
  2195. });
  2196. }
  2197. if(type==="mafia") {
  2198. chat.appendChild(node);
  2199. }
  2200. else {
  2201. chat.insertBefore(node, chat.lastChild);
  2202. }
  2203. };
  2204. function request(method, url, callback) {
  2205. var req=new XMLHttpRequest();
  2206. req.open(method, url, true);
  2207. req.onreadystatechange=function(event) {
  2208. if(this.readyState===4) {
  2209. callback.call(this, this.responseText);
  2210. }
  2211. };
  2212. req.send();
  2213. };
  2214. function arand(array) {
  2215. return array[Math.floor(Math.random()*array.length)];
  2216. };
  2217. function rchar(x, y) {
  2218. return String.fromCharCode(
  2219. x+Math.floor(Math.random()*(y-x))
  2220. );
  2221. };
  2222. function sformat(string, data) {
  2223. return string.replace(/\$(\d+)/g, function(match, i) {
  2224. return data[i-1];
  2225. });
  2226. };
  2227.  
  2228. // keep chat
  2229. if(type==="mafia") {
  2230. document.querySelector("#speak_container")
  2231. .style.cssText="display: initial !important";
  2232. }
  2233.  
  2234. // townie input
  2235. var chat=document.getElementById(type==="mafia" ? "window" : "window_i"),
  2236. typebox=document.getElementById(type==="mafia" ? "typebox" : "chatbar");
  2237. typebox.addEventListener("keydown", function(event) {
  2238. if(event.which===13 && this.value[0]==="/") {
  2239. if(type==="mafia") {
  2240. ej.run(this.value.substring(1), ej.lchat);
  2241. this.value="";
  2242. }
  2243. else {
  2244. ej.run(this.value.substring(1), ej.llobby);
  2245. this.value="";
  2246. }
  2247. }
  2248. });
  2249. if(type==="mafia") {
  2250. var notebox=document.querySelector("textarea.notes");
  2251. notebox.addEventListener("focus", function(event) {
  2252. if(ej.settings & UNOTES && !ranked) {
  2253. this.value=notes[document.querySelector(".user_header > h2").textContent];
  2254. }
  2255. });
  2256. notebox.addEventListener("keyup", function(event) {
  2257. if(ej.settings & UNOTES && !ranked) {
  2258. notes[document.querySelector(".user_header > h2").textContent]=this.value;
  2259. }
  2260. });
  2261. }
  2262.  
  2263. // clickables
  2264. if(window.vocabs) {
  2265. vocabs.push("https?://\\S+");
  2266. }
  2267. window.addEventListener("click", function(event) {
  2268. var classList=event.target.classList;
  2269. if(classList.contains("msg")) {
  2270. if(ej.settings & MSGMRK) {
  2271. var mark=keys & K_SHIFT ? "ej_mark_alt" : "ej_mark";
  2272. if(classList.contains(mark)) {
  2273. classList.remove(mark);
  2274. }
  2275. else {
  2276. classList.add(mark);
  2277. classList.remove(keys & K_SHIFT ? "ej_mark" : "ej_mark_alt");
  2278. }
  2279. }
  2280. }
  2281. else if(classList.contains("meet_username")) {
  2282. ej.run("vote "+(
  2283. event.target.textContent==="You" ?
  2284. user : event.target.textContent
  2285. ), ej.lchat);
  2286. }
  2287. else if(classList.contains("acronym")) {
  2288. if(/https?:\/\//i.test(event.target.textContent)) {
  2289. window.open(event.target.textContent, "_blank");
  2290. event.stopPropagation();
  2291. }
  2292. }
  2293. }, true);
  2294.  
  2295. // clean up
  2296. var last_error=null;
  2297. window.addEventListener("error", function(event) {
  2298. var message=event.error.message;
  2299. if(message!==last_error) {
  2300. log("You've got error!", "bold");
  2301. log(last_error=message);
  2302. }
  2303. });
  2304. window.addEventListener("beforeunload", function(event) {
  2305. localStorage.ejs=ej.settings;
  2306. if(ej.settings & UNOTES && !ranked) {
  2307. localStorage.notes=JSON.stringify(notes);
  2308. }
  2309. if(window.setup_id) {
  2310. localStorage.ejsid=setup_id;
  2311. }
  2312. });
  2313. window.addEventListener("keyup", function(event) {
  2314. if(event.which===16) {
  2315. keys&=~K_SHIFT;
  2316. }
  2317. else if(event.which===192) {
  2318. keys&=~K_DEBUG;
  2319. }
  2320. });
  2321. if(~navigator.userAgent.indexOf("Windows")) {
  2322. window.addEventListener("keydown", function(event) {
  2323. if(event.ctrlKey) {
  2324. if(event.which===66) {
  2325. sock.cmd("option", {
  2326. field: "fastgame"
  2327. });
  2328. sock.cmd("option", {
  2329. field: "nospectate"
  2330. });
  2331. }
  2332. else if(event.which===81) {
  2333. ej.run("fq "+user+" "+typebox.value, ej.lchat);
  2334. typebox.value="";
  2335. }
  2336. }
  2337. else if(event.target.value===undefined) {
  2338. if(event.which===16) {
  2339. keys|=K_SHIFT;
  2340. }
  2341. else if(event.which===192) {
  2342. keys|=K_DEBUG;
  2343. }
  2344. if(~keys & K_DEBUG) {
  2345. typebox.focus();
  2346. }
  2347. }
  2348. });
  2349. }
  2350.  
  2351. }
  2352.  
  2353. // add node
  2354. function inject(parent, tag, content) {
  2355. var node=document.createElement(tag);
  2356. node.appendChild(
  2357. document.createTextNode(content)
  2358. );
  2359. return parent.appendChild(node);
  2360. };
  2361.  
  2362. // jack in
  2363. inject(document.head, "style", "\
  2364. .log {\
  2365. color: #bb4444;\
  2366. }\
  2367. .notop {\
  2368. margin-top: 0 !important\
  2369. }\
  2370. .ej_mark {\
  2371. background-color: rgba(250, 50, 250, 0.5);\
  2372. }\
  2373. .ej_mark_alt {\
  2374. background-color: rgba(250, 150, 0, 0.5);\
  2375. }\
  2376. .ej_highlight {\
  2377. background-color: rgba(255, 255, 0, 0.5);\
  2378. }\
  2379. .ej_img * {\
  2380. max-width: 100%;\
  2381. }\
  2382. .meet_username {\
  2383. cursor: pointer;\
  2384. }\
  2385. #lobbychat #window {\
  2386. width: 100% !important;\
  2387. }\
  2388. #lobbychat #window_i {\
  2389. width: auto !important;\
  2390. }\
  2391. ").type="text/css";
  2392. inject(document.head, "style", "\
  2393. #game_container.graphi .cmds {\
  2394. position: relative;\
  2395. z-index: 1;\
  2396. height: auto;\
  2397. width: 300px !important;\
  2398. padding: 8px;\
  2399. background: rgba(255,255,255,0.8);\
  2400. }\
  2401. #game_container.graphi .userbox {\
  2402. width: auto !important;\
  2403. }\
  2404. #game_container.graphi .canvas {\
  2405. float: right;\
  2406. max-width: 40%;\
  2407. margin-right: -256px;\
  2408. overflow: hidden;\
  2409. }\
  2410. #game_container.graphi #window {\
  2411. display: block !important\
  2412. }\
  2413. #game_container.graphi #system-messages {\
  2414. width: 100%;\
  2415. font-size: .8em;\
  2416. background: rgba(255,255,255,0.8);\
  2417. }\
  2418. #game_container.graphi #canvas-player-area {\
  2419. position: relative;\
  2420. z-index: 1;\
  2421. left: 0 !important;\
  2422. max-width: 100%;\
  2423. }\
  2424. ").type="text/css";
  2425. setTimeout(function() {
  2426. inject(document.body, "script", "("+emjack.toString()+")()")
  2427. .type="text/javascript";
  2428. document.body.addEventListener("contextmenu", function(event) {
  2429. event.stopPropagation();
  2430. }, true);
  2431. });
Add Comment
Please, Sign In to add comment