TheWest-Notifier

Plays a notification sound, when specified events are triggered in the browser game The West!

当前为 2018-08-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name TheWest-Notifier
  3. // @namespace TWNotifier_M77
  4. // @author Meuchelfix77 (updated by Tom Robert)
  5. // @description Plays a notification sound, when specified events are triggered in the browser game The West!
  6. // @include https://*.the-west.*/game.php*
  7. // @exclude https://classic.the-west.net*
  8. // @version 1.022
  9. // @icon http://twm.pf-control.de/TWNotifier/favicon.ico
  10. // @grant none
  11. // ==/UserScript==
  12. (function (fn) {
  13. var script = document.createElement('script');
  14. script.setAttribute('type', 'text/javascript');
  15. script.textContent = '(' + fn.toString() + ')();';
  16. (document.head || document.body || document.documentElement).appendChild(script);
  17. script.parentNode.removeChild(script);
  18. })(function () {
  19. TWN = {
  20. version: '1.022',
  21. name: 'TheWest-Notifier',
  22. author: 'Meuchelfix77 (updated by Tom Robert)',
  23. website: 'https://greasyfork.org/scripts/16917',
  24. updateUrl: 'https://tomrobert.safe-ws.de/sUp.js',
  25. updateAd: 'http://adf.ly/1WcofT',
  26. LANGUAGE: (localStorage.getItem('scriptsLang') || Game.locale.substr(0, 2)),
  27. init: function () {
  28. switch (TWN.LANGUAGE) {
  29. default:
  30. TWN.lang = {
  31. translator: 'Meuchelfix77',
  32. notifications: 'Notifications',
  33. confirmationTitle: 'Confirmation',
  34. confirmation: 'Are you sure to remove this notification?',
  35. types: {
  36. messages: 'Messages',
  37. reports: 'Reports',
  38. townforum: 'Townforum',
  39. friends: 'Friends',
  40. wayFinished: 'Way finished',
  41. noQueue: 'Empty job queue',
  42. newItem: 'New item',
  43. nickInChat: 'Nickname in chat',
  44. },
  45. sounds: {
  46. bum: 'Bum',
  47. chime: 'Chime',
  48. coin: 'Coin',
  49. coin2: 'Coin 2',
  50. icq: 'ICQ',
  51. qip: 'QIP',
  52. tinkle: 'Tinkle',
  53. trumpet: 'Trumpet',
  54. vk: 'VK',
  55. custom: 'Custom',
  56. },
  57. event: 'Event',
  58. info: 'Information',
  59. remove: 'Remove this notification',
  60. listen: 'Listen to this sound',
  61. sound: 'Sound',
  62. soundFile: 'Sound file',
  63. soundInfo: 'Warning! Not all files can be played in your browser.',
  64. desc: {
  65. messages: 'Telegram received:',
  66. reports: 'Report received of type:',
  67. townforum: 'New forum post in:',
  68. friends: 'Friend(s) online:',
  69. wayFinished: 'Way finished:',
  70. noQueue: 'Empty job queue:',
  71. newItem: 'New item in inventory:',
  72. nickInChat: 'Nickname typed in chat:',
  73. },
  74. reportTypes: {
  75. all: 'All',
  76. work: 'Work',
  77. duels: 'Duels',
  78. achvmnt: 'Achievements',
  79. fort: 'Fort battles',
  80. other: 'Other',
  81. },
  82. add: 'Add notification',
  83. wayFinishedInfo: 'Triggers when you have finished your way and reached your destination.',
  84. reportInfo: '<b>Warning!</b> This will cause problems with the blinking messages button on the bottom screen.<br>Selecting <i>All</i> will solve these problems.',
  85. noQueueInfo: 'Triggers when there are no more job assignments in you job queue.',
  86. messagesInfo: 'Triggers when you receive a telegram.',
  87. friendListInfo: 'Seperate multiple friends with a semicolon (;)',
  88. townforumInfo: 'Triggers when somebody writes a post in the forum<span id="selectedForum"></span>.',
  89. newItemInfo: 'Triggers when you find, buy or get a new item.',
  90. nickInChatInfo: 'Triggers when your name was typed in the chat. Seperate more nicks with a semicolon (;)',
  91. install: 'Install',
  92. cancel: 'Cancel',
  93. update: 'Update',
  94. updateAvailable: 'A new version of the script is available',
  95. };
  96. break;
  97. case ('de'):
  98. TWN.lang = {
  99. translator: 'Meuchelfix77',
  100. notifications: 'Benachrichtigungen',
  101. confirmationTitle: 'Bestätigung',
  102. confirmation: 'Willst du diese Benachrichtigung wirklich löschen?',
  103. types: {
  104. messages: 'Telegramme',
  105. reports: 'Berichte',
  106. townforum: 'Stadtforum',
  107. friends: 'Freunde',
  108. wayFinished: 'Weg beendet',
  109. noQueue: 'Keine Arbeitsaufträge',
  110. newItem: 'Neues Item',
  111. nickInChat: 'Spielername im Chat',
  112. },
  113. sounds: {
  114. bum: 'Bum',
  115. chime: 'Glockenspiel',
  116. coin: 'Münze',
  117. coin2: 'Münze 2',
  118. icq: 'ICQ',
  119. qip: 'QIP',
  120. tinkle: 'Glitzer',
  121. trumpet: 'Trompete',
  122. vk: 'VK',
  123. custom: 'Eigene',
  124. },
  125. event: 'Ereignis',
  126. remove: 'Diese Benachrichtigung löschen',
  127. listen: 'Anhören',
  128. sound: 'Ton',
  129. soundFile: 'Audio-Datei',
  130. soundInfo: 'Achtung! Nicht alle Dateien werden von deinem Browser unterstützt.',
  131. desc: {
  132. messages: 'Telegramm erhalten:',
  133. reports: 'Bericht erhalten vom Typ:',
  134. townforum: 'Neuer Foren-Beitrag in:',
  135. friends: 'Freund(e) online:',
  136. wayFinished: 'Weg beendet:',
  137. noQueue: 'Keine weiteren Aufträge:',
  138. newItem: 'Neues Item im Inventar:',
  139. nickInChat: 'Name im Chat erwähnt:',
  140. },
  141. reportTypes: {
  142. all: 'Alle',
  143. work: 'Arbeiten',
  144. duels: 'Duelle',
  145. achvmnt: 'Erfolge',
  146. fort: 'Fortkämpfe',
  147. other: 'Sonstige',
  148. },
  149. add: 'Benachrichtigung hinzufügen',
  150. wayFinishedInfo: 'Wird ausgelöst, wenn du dein Ziel erreicht hast.',
  151. reportInfo: '<b>Achtung!</b> Diese Einstellung verursacht ein Problem mit der blinkenden Nachrichten-Schaltfläche am unteren Bildrand.<br>Die Option <i>Alle</i> behebt dieses Problem.',
  152. noQueueInfo: 'Wird ausgelöst, wenn du keine Arbeiten mehr in der Warteschlange hast.',
  153. messagesInfo: 'Wird ausgelöst, wenn du ein Telegramm erhälst.',
  154. friendListInfo: 'Trenne mehrere Freunde mit einem Semikolon (;)',
  155. townforumInfo: 'Wird ausgelöst, wenn jemand einen Beitrag im Stadtforum<span id="selectedForum"></span> verfasst.',
  156. newItemInfo: 'Wird ausgelöst wenn du ein neues Item findest oder kaufst.',
  157. nickInChatInfo: 'Wird ausgelöst wenn dein Name im Chat steht. Trenne weitere Nicks mit einem Semikolon (;)',
  158. install: 'Installieren',
  159. cancel: 'Abbrechen',
  160. };
  161. break;
  162. case ('pl'):
  163. TWN.lang = {
  164. translator: 'Darius II',
  165. notifications: 'Powiadomienia',
  166. confirmationTitle: 'Potwierdzenie',
  167. confirmation: 'Chcesz usunąć to powiadomienie?',
  168. types: {
  169. messages: 'Wiadomości',
  170. reports: 'Raporty',
  171. townforum: 'Forum',
  172. friends: 'Znajomi',
  173. wayFinished: 'Dotarcie do celu',
  174. noQueue: 'Brak zadań',
  175. newItem: 'New item',
  176. nickInChat: 'Nickname in chat',
  177. },
  178. sounds: {
  179. bum: 'Bum',
  180. chime: 'Kurant',
  181. coin: 'Kucie',
  182. coin2: 'Kucie 2',
  183. icq: 'ICQ',
  184. qip: 'QIP',
  185. tinkle: 'Dzwonek',
  186. trumpet: 'Trąbka',
  187. vk: 'VK',
  188. custom: 'Własny',
  189. },
  190. event: 'Zdarzenie',
  191. remove: 'Usuń zdarzenie',
  192. listen: 'Odsłuchaj',
  193. sound: 'Dźwięk',
  194. soundFile: 'Plik dźwięku',
  195. soundInfo: 'Uwaga! Nie wszystkie typy plików dźwiękowych mogą być odtwarzane w przeglądarce.',
  196. desc: {
  197. messages: 'Otrzymano wiadomość:',
  198. reports: 'Typ raportu:',
  199. townforum: 'Nowy wpis w:',
  200. friends: 'Pojawił się znajomy/a :',
  201. wayFinished: 'Ośiągnięto cel:',
  202. noQueue: 'Brak zadań:',
  203. newItem: 'New item in inventory:',
  204. nickInChat: 'Nickname typed in chat:',
  205. },
  206. reportTypes: {
  207. all: 'Wszystkie',
  208. work: 'Praca',
  209. duels: 'Pojedynki',
  210. achvmnt: 'Osiągnięcia',
  211. fort: 'Fortowe',
  212. other: 'Pozostałe',
  213. },
  214. add: 'Dodaj powiadomienie',
  215. wayFinishedInfo: 'Odtworzy dźwięk kiedy dotrzesz na wyznaczoną pozycję.',
  216. reportInfo: '<b>Uwaga!</b> Ten wybór powoduje problemy z migotaniem przycisku "wiadomości/raporty", wybrór <i>Wszystkie</i> rozwiąże ten problem.',
  217. noQueueInfo: 'Odtworzy dźwięk, kiedy zostaną wykonane wszystkie zadania.',
  218. messagesInfo: 'Odtworzy dźwięk, kiedy otrzymasz telegram.',
  219. friendListInfo: 'Oddziel znajomych średnikiem (;)',
  220. townforumInfo: 'Odtworzy dźwięk, kiedy ktoś napisze wiadomośc na forum w zakładce: <span id="selectedForum"></span>.',
  221. newItemInfo: 'Triggers when you find, buy or get a new item.',
  222. nickInChatInfo: 'Triggers when your name was typed in the chat. Seperate more nicks with a semicolon (;)',
  223. install: 'Zainstaluj',
  224. cancel: 'Anuluj',
  225. };
  226. break;
  227. case ('pt'):
  228. TWN.lang = {
  229. translator: 'jccwest',
  230. notifications: 'Notificações',
  231. confirmationTitle: 'confirmação',
  232. confirmation: 'Tem certeza que deseja remover esta notificação?',
  233. types: {
  234. messages: 'Mensagens',
  235. reports: 'Relatórios',
  236. townforum: 'Fórum da cidade',
  237. friends: 'Amigos',
  238. wayFinished: 'Chegou ao destino',
  239. noQueue: 'Sem trabalhos',
  240. newItem: 'Novo item no inventário',
  241. nickInChat: 'Nickname in chat',
  242. },
  243. sounds: {
  244. bum: 'Bum',
  245. chime: 'Chime',
  246. coin: 'Coin',
  247. coin2: 'Coin 2',
  248. icq: 'ICQ',
  249. qip: 'QIP',
  250. tinkle: 'Tinkle',
  251. trumpet: 'Trompete',
  252. vk: 'VK',
  253. custom: 'Custom',
  254. },
  255. event: 'Evento',
  256. info: 'Informação',
  257. remove: 'Remover esta notificação',
  258. listen: 'reproduzir o som',
  259. sound: 'Som',
  260. soundFile: 'arquivo de som',
  261. soundInfo: 'Aviso! Nem todos os arquivos podem ser reproduzidos no seu navegador.',
  262. desc: {
  263. messages: 'Telegrama recebido:',
  264. reports: 'Relatório recebeu do tipo:',
  265. townforum: 'Novo post no fórum:',
  266. friends: 'Amigo(s) on-line:',
  267. wayFinished: 'Chegou ao destino:',
  268. noQueue: 'Sem trabalhos:',
  269. newItem: 'Novo item no inventário:',
  270. nickInChat: 'Nickname typed in chat:',
  271. },
  272. reportTypes: {
  273. all: 'Todos',
  274. work: 'Trabalho',
  275. duels: 'Duelos',
  276. achvmnt: 'Conquistas',
  277. fort: 'Batalhas no forte',
  278. other: 'Outro',
  279. },
  280. add: 'Adicionar notificação',
  281. wayFinishedInfo: 'Avisa quando tiver terminado o meu caminho e a chegada ao destino.',
  282. reportInfo: '<b>Aviso!</b> Isto irá causar problemas com o botão piscando mensagens na tela inferior seleção <i>Todos</i> vai resolver estes problemas.',
  283. noQueueInfo: 'Avisa quando não há mais trabalhos atribuídos.',
  284. messagesInfo: 'Avisa quando recebe um telegrama.',
  285. friendListInfo: 'Separe vários amigos com um ponto e vírgula (;)',
  286. townforumInfo: 'Avisa quando alguém escreve um post no fórum <span id="selectedForum"></span>.',
  287. newItemInfo: 'Avisa quando encontra,ou compra um novo item.',
  288. nickInChatInfo: 'Triggers when your name was typed in the chat. Seperate more nicks with a semicolon (;)',
  289. install: 'Instalar',
  290. cancel: 'Cancelar',
  291. };
  292. break;
  293. case ('el'):
  294. TWN.lang = {
  295. translator: 'Timemod Herkumo',
  296. notifications: 'Ειδοποιήσεις',
  297. confirmationTitle: 'Επιβεβαίωση',
  298. confirmation: 'Είστε βέβαιοι ότι θέλετε να καταργήσετε αυτήν την ειδοποίηση;',
  299. types: {
  300. messages: 'Μυνήματα',
  301. reports: 'Αναφορές',
  302. townforum: 'Φόρουμ πόλης',
  303. friends: 'Φιλοι',
  304. wayFinished: 'Τέλος προορισμού',
  305. noQueue: 'Κενή ουρά εργασίας',
  306. newItem: 'Νέο αντικείμενο',
  307. nickInChat: 'Ψευδώνυμο στην συνομιλία',
  308. },
  309. sounds: {
  310. bum: 'Bum',
  311. chime: 'Κουδούνι',
  312. coin: 'Νόμισμα',
  313. coin2: 'Νόμισμα 2',
  314. icq: 'ICQ',
  315. qip: 'QIP',
  316. tinkle: 'Λάμψη',
  317. trumpet: 'Τρομπέτα',
  318. vk: 'VK',
  319. custom: 'Προσαρμοσμένο',
  320. },
  321. event: 'Εκδήλωση',
  322. info: 'Πληροφορίες',
  323. remove: 'Κατάργηση αυτής της ειδοποίησης',
  324. listen: 'Ακούστε αυτόν τον ήχο',
  325. sound: 'Ήχοι',
  326. soundFile: 'Αρχείο ήχου',
  327. soundInfo: '<b>Προειδοποίηση!</b><br>Δεν είναι δυνατή η αναπαραγωγή όλων των αρχείων στο πρόγραμμα περιήγησής σας.',
  328. desc: {
  329. messages: 'Λάβατε νέο τηλεγάφημα:',
  330. reports: 'Λάβατε νέα αναφορά:',
  331. townforum: 'Νέο θέμα στο Φόρουμ:',
  332. friends: 'Συνδεδεμένος φίλος:',
  333. wayFinished: 'Προορισμός:',
  334. noQueue: 'Κενή ουρά εργασίας:',
  335. newItem: 'Νέο αντικείμενο:',
  336. nickInChat: 'Ψευδόνυμο στο τσατ:',
  337. },
  338. reportTypes: {
  339. all: 'Όλα',
  340. work: 'Εργασίες',
  341. duels: 'Μονομαχίες',
  342. achvmnt: 'Επιτεύγματα',
  343. fort: 'Μάχες Οχυρού',
  344. other: 'Άλλο',
  345. },
  346. add: 'Προσθήκη ειδοποίησης',
  347. wayFinishedInfo: 'Ενεργοποιείται όταν φτάσετε στον προορισμό σας.',
  348. reportInfo: '<b>Προειδοποίηση!</b><br>Αυτό θα προκαλέσει προβλήματα με την αναλαμπή του κουμπιού μηνυμάτων στην κάτω μπάρα μενού.<br>Η επιλογή <i>"Όλα"</i> θα λύσει αυτά τα προβλήματα.',
  349. noQueueInfo: 'Ενεργοποιείται όταν δεν υπάρχουν εργασίες στην ουρά εργασίας.',
  350. messagesInfo: 'Ενεργοποιείται όταν λαμβάνετε ένα τηλεγράφημα.',
  351. friendListInfo: 'Ξεχωρίστε πολλούς φίλους με ένα ερωτηματικό (;)',
  352. townforumInfo: 'Ενεργοποιείται όταν κάποιος γράφει μια ανάρτηση στο φόρουμ .',
  353. newItemInfo: 'Ενεργοποιείται όταν βρίσκετε, αγοράζετε ή λαμβάνετε ένα νέο αντικείμενο.',
  354. nickInChatInfo: 'Ενεργοποιείται όταν αναφέρεται το όνομά σας στη συζήτηση. Seperate more nicks with a semicolon (;)',
  355. install: 'Εγκατάσταση',
  356. cancel: 'Ματαίωση',
  357. };
  358. break;
  359. } // Init all modules of TWNotifier
  360.  
  361. TWN.initStyleSheet();
  362. TWN.settings.init();
  363. TWN.notifications.init();
  364. },
  365. roomsListening: [
  366. ],
  367. // init the global stylesheet
  368. initStyleSheet: function () {
  369. var css = $('<style id="TWNotifierStyles"></style>');
  370. $(document.head || document.body || document.documentElement).append(css);
  371. },
  372. // add global CSS information
  373. addStyle: function (css) {
  374. var styles = $('#TWNotifierStyles');
  375. styles.html(styles.html() + '\n' + css);
  376. },
  377. // returns a value from our storage
  378. get: function (key, val) {
  379. return (localStorage.getItem('TWNotifier_' + key) || val);
  380. },
  381. // sets a value pair in our storage
  382. set: function (key, val) {
  383. localStorage.setItem('TWNotifier_' + key, val);
  384. },
  385. // removes a key-value pair from our storage
  386. remove: function (key) {
  387. localStorage.removeItem('TWNotifier_' + key);
  388. },
  389. showMessage: function (text, icon) {
  390. new UserMessage(text, icon).show();
  391. },
  392. // append the specified function
  393. appendFunction: function (oldFn, newFn, _thisOld, _thisNew) {
  394. var fn = parent,
  395. i = 1; // start for finding the function to replace
  396. // every loop we get one step deeper/closer to our function to replace/append to
  397. while (fn[oldFn[i - 1]][oldFn[i]]) {
  398. fn = fn[oldFn[i - 1]];
  399. i++;
  400. }
  401. var tmpFn = fn[oldFn[i - 1]]; // avoid recursion
  402. fn[oldFn[i - 1]] = function () {
  403. newFn.apply(_thisNew, arguments); // and afterwards our new
  404. return tmpFn.apply(this, arguments); // call the old function;
  405. };
  406. }
  407. };
  408. TWN.images = {
  409. right_menu: 'data:image/png;base64,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',
  410. right_menu_hover: 'data:image/png;base64,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',
  411. sound: 'data:image/png;base64,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',
  412. remove: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAcCAYAAAB75n/uAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAMPSURBVHja7FVNaFxVFP7uzJ15781rMy6CUkNJ0ygi1W40i4BCgmKF0k1FxEXFpeDCZUEFKZKCLnSZlRuz8GfhQgISxa1SkbQF0xICFYUSDZ1kOjPv595z7j0uJplMJplxmupKP3jv3Xu/8853zjvn3qfeeu2ZK7Ozs7i+fMViF6rnec/YupuVZ2ZmRDvna8WihveSHWCn7nHeATsfFbUWbclt6FIAdr51CEd9BSy5uKgDaENuU5dDMLsGAOk1lPaa7E4HovNpjaWRUhAqneW0EYSx5Ja3dq3UwTVQf1MT2Q0kM2yDMBbdSkwtqowgy6nWE4zavisAqjJ57stuNru1+Mo+/yKdDNPMqiCMoY3lrFQOYcil3ZYA4LcjGj11fum9dy6CmAEAJa1xaQ5f3Fn56ky/ZFqpLUVxVXSjZZpRXFXNxDS6Izgx9eoP3S9cmvtgn5PRU+eXdsa//vTZdDfXaOVBFFehk9zmYTyCRivvZPDkzOtXP5p7e+iev7ayhk+BH5e/++T0zlozNUeiI1XoZsvklfgBbNbTPfugnjBq9TqMIVhrkVuD3BCsJWRZjjTLkKQp0iQFMQEANjaTjo+7zTyvxFWlDbHT5QCZYdct8P6HH+ONCy9h+edrIC9g50CWYcjCWIYlhvcekxMTWF1b2969KXWaICcuB7HS7UFlD7kwf3n8wpvv/vboIydRa1mcfvwkmhlj8Zvv8fz00/j9j02srt7E8bExhFGEX26sYGH+8nh3gN6LFHVJtLHsykGEZmL2ZEC2refYgYnA7OC9h3MM53bGDiICsoQ7Wwn3nhZh5Si0Jed1KUCSWd/NOubhKqzUQNtCP4LYDucfAA+w7SvAw2YAgOgQGTDRkO4VmOlfzEDhcDXwvl1zL+0DSUTgvUf7MBGI+E4NdmwPgu5HFAtt7WennoDxgC8QXnzhOdQbTURRhInJx+AdIwgCKKUGNsFTIgKl1HovOXv25du31/9EoaCgtv8SSqnOJSJ4+KEH8e3Xn48d4PuYiAwWuE8cE5H+Nfin8L/Af0DgrwEAWMmrNSQDjVcAAAAASUVORK5CYII=',
  413. listen: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAATLSURBVHjabNTbb1MFAAbw75ye09Nz2q5dt17W7tbuonNuMBzb2Mhgg8GEcQk6zEIwBo2LBucLWaIhM2AkmvhiYiJoNAIPE0RRUCAaQHCwQdmVrcuQrbtQ1nbrveecrrfjAwmJke8P+D18+fIRhw/3wOl0guM4WK2FoGkasZgAgITX6yH6+vq6Ozo6vrdYzB6fz4f1ja3Q6TIQE/zs0VO+a6KsgP2iK2u1UkHBH0mBwjMilyuwvLyEeCI14PP5a7q7u38F4Cl/oRJvHXgXl/+4ApohxKWoqS7E5uOrC/6z77SRe8UVGcj/Y3J4PB46EAz1t7Zuq6mtrYNGo+HVKiWOn/gaNJVG7/VIZ/6LjYqe1/jn6PB93J3Xtf8+EGnjFNITUJKkp9ji4qI6EAzd6+jYV9e2/WVwnAICH5FtbG7BmtVFOPZt36E7gc3HT15V/11XXfZgY8FIj285gJH5jG+cjwSQgiDA51tGMBjE9PSMJZFIDnV2dlY2NzWCokgkk0kY9Nnxli1bMexwoWVt1qWKHJ9o/wfVJ2/q2zet4T5W8zfgiipMjvlUK5mbm3d+1+49A+vqG/qtVpujq+tgcW1NNQDA7fZi1jkdb25aHxF1Oz797GKWo6S4wNFWNr4rEVnEDQdOxekiFKrnTnu9IgIC207t3fvqbovFDEkCvF4vGEaOyckpLPv8CIcjCIWCKU1GqeSPKWseBjVl311PflhvUx7T2e3BgLBT65eKzAWGv0475pz7l4WyanJmxhmcevAQExMOjI6Ooe/WABYWXKAoCrkWMzgugx0cHIo+zw68kq92YWiWOvI4ooNe4b0YiaTgiXL16XRyisUSxCSRR+Xl50kmkwnxlRWwrAIGgwFKJQeSfDIAiyUHt2/3KxemRwMaIguhiJ4SUypwTHp6RQyDj2mzpDQhyLCCNMBR7sXHRDqVhCAIEEUBRqPhKQYAIAhUlBfx2ZbSDK+dgM7Ap7RsDHwsbY2nJSiZRCBGSlxCokASEKne3jNavcGIWCyGJa8XllwzamtqYLNZoVar4Vtyi+XlpaqpcMXPc34SLQ3po2ZNGI+DzE5ltgzZXPjWEmRl4YQKNJGcp0w55ps0Lc9RKBSSXC4vCYXCRG/vDygtLUVJSQn8gZAs4A8SL2VKIzZ9IP/t7dlHf/xpsXkhasusKk7EjfJHrsvuxCcpWTa0dGCQioZDG2acM2AYBiZTTvmqVZVXQ+GIcWR4ELNzc0hJhPy3S3+q69ZdPvTRvqZD4+NTpWf7dRdYrRUbKuVvMCkXHrjVr5uKNNAro+dIgiRB03IwjALJZHJi0jFepVJyszt27IZOlwU+GkWUF5kz585iXVUhrt1x7RqZVysbKhQjb26Rei/emPvAR6whCrMEb1UJc4l80jsBAKAoGViWWxwbHa5yuRYcTU2bUFBohUqlTA0P2XHn3gQOH9z2+XrL8HsHNjMNd+1DtivjpmNGcz6qbGJnnon77zlIkgSCIJCpzQy6Hs1Xj40NT8bjcUSjPBuLxfF+VxdSybS0f6vpS7fzltB9Ymk6pVqL+uLQ+Z2Nhl/4mPTs+0pLEjQajSgKfLWMJI709PREDAY9eF7A5NRD1NQ3gI8GOaP2vl1Hu9iu9rI9apZFPL6CfwcAFv8pW2JrAdUAAAAASUVORK5CYII=',
  414. add: 'data:image/png;base64,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',
  415. info: 'data:image/png;base64,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',
  416. };
  417. TWN.sounds = [
  418. 'bum', 'chime', 'coin', 'coin2', 'icq', 'qip', 'tinkle', 'trumpet', 'vk',
  419. ];
  420. TWN.notifications = {
  421. list: {
  422. length: 0
  423. },
  424. init: function () {
  425. // Load notifications
  426. this.list.length = TWN.get('notificationCount', 0);
  427. for (var i = 0; i < this.list.length; i++) {
  428. var data = TWN.get('notification_' + i, '');
  429. if (data == '') {
  430. this.remove(i);
  431. i = 0;
  432. continue;
  433. }
  434. data = JSON.parse(data);
  435. this.list[i] = data;
  436. }
  437. // append TW-functions with TWNotifier-functionality
  438. // friend online
  439. TWN.appendFunction([
  440. 'west', 'notification', 'ToastOnlineNotification', 'prototype', 'init'
  441. ], function (name) {
  442. var sound = '';
  443. for (var i = 0; i < this.list.length; i++) {
  444. if (this.list[i].event == 'friends') {
  445. if (this.list[i].info == '*')
  446. sound = this.list[i].sound;
  447. else if (this.list[i].info.split(';').includes(name)) {
  448. sound = this.list[i].sound;
  449. break;
  450. }
  451. }
  452. }
  453. TWN.notifications.playSound(sound);
  454. }, west.notification.ToastOnlineNotification.prototype._super.prototype, this);
  455. // new report
  456. TWN.appendFunction(['Character', 'setToRead'], function (type, status) {
  457. if (status == false)
  458. return;
  459. // TOWNFORUM
  460. if (type == 'townforum') {
  461. var notifications = {
  462. length: 0
  463. };
  464. var custom = 0; // 0 = no notification, 1 = only all; 2 = custom notification
  465. for (var notification in TWN.notifications.list) {
  466. if (TWN.notifications.list[notification].event == 'townforum') {
  467. notifications[notifications.length] = TWN.notifications.list[notification].info;
  468. notifications.length++;
  469. if (TWN.notifications.list[notification].info == '*' && custom == 0)
  470. custom = 1;
  471. else
  472. custom = 2;
  473. }
  474. } // No notifications for forum
  475.  
  476. if (custom == 0 || notifications.length == 0)
  477. return;
  478. // no custom notifications
  479. if (custom == 1) {
  480. TWN.notifications.playSound(TWN.notifications.list[TWN.notifications.getIndex('townforum', '*')].sound);
  481. return;
  482. } // custom notifications
  483.  
  484. $.ajax('forum.php', {
  485. complete: function (data) {
  486. var DOM = $.parseHTML(data.responseText);
  487. var forumList = $('#forum_list', DOM);
  488. forumList.children().each(function (i, el) {
  489. if ($(el).hasClass('background')) {
  490. var index = TWN.notifications.getIndex('townforum', $(el).find('span').text());
  491. if (index != -1) {
  492. TWN.notifications.playSound(TWN.notifications.list[index].sound);
  493. return false;
  494. }
  495. }
  496. });
  497. }
  498. });
  499. return;
  500. }
  501. // MESSAGES
  502. if (type == 'messages') {
  503. var index = TWN.notifications.getIndex('messages');
  504. if (index != -1)
  505. TWN.notifications.playSound(TWN.notifications.list[index].sound);
  506. return;
  507. }
  508. // REPORTS
  509. if (type == 'reports') {
  510. // If no report types are specified, just play the sound for 'all reports', if specified (no requests)
  511. var allSound = 'data:audio/ogg;base64,;';
  512. for (var noti in TWN.notifications.list) {
  513. if (TWN.notifications.list[noti].event == 'reports') {
  514. if (TWN.notifications.list[noti].info != 'all') {
  515. allSound = '';
  516. break;
  517. } else
  518. allSound = TWN.notifications.list[noti].sound;
  519. }
  520. }
  521. if (allSound != '') {
  522. TWN.notifications.playSound(allSound);
  523. return;
  524. }
  525. // Send requests to check if there are new reports for the specified report types
  526. Ajax.remoteCall('reports', 'get_reports', {
  527. page: 0,
  528. folder: 'all'
  529. }, function (json) {
  530. if (json.error != false || !json.reports[0])
  531. return;
  532. var report_id = json.reports[0].report_id; // latest report
  533. // create counter
  534. var sounds = {},
  535. counter = (TWN.notifications.getIndex('reports', 'all') == -1 ? -6 : 0);
  536. for (type in TWN.lang.reportTypes) {
  537. var index = TWN.notifications.getIndex('reports', type);
  538. if (index != -1) {
  539. sounds[type] = TWN.notifications.list[index].sound;
  540. counter++;
  541. } else
  542. sounds[type] = '';
  543. }
  544. var gen = function (type, report) {
  545. return function (json) {
  546. if (json.error != false || !json.reports[0] || sounds[type] == '')
  547. return;
  548. if (json.reports[0].report_id == report) {
  549. counter = 0;
  550. TWN.notifications.playSound(sounds[type]);
  551. } else {
  552. counter--;
  553. if (counter == 0)
  554. TWN.notifications.playSound(sounds.all);
  555. }
  556. };
  557. };
  558. for (type in sounds)
  559. Ajax.remoteCall('reports', 'get_reports', {
  560. page: 0,
  561. folder: type
  562. }, gen(type, report_id));
  563. });
  564. return;
  565. }
  566. }, Character, this);
  567. // way finished
  568. TWN.appendFunction(['OnGoingWayFinishedEntry'], function () {
  569. for (var i = 0; i < this.list.length; i++) {
  570. if (this.list[i].event == 'wayFinished') {
  571. this.playSound(this.list[i].sound);
  572. break;
  573. }
  574. }
  575. }, OnGoingEntry, TWN.notifications);
  576. OnGoingWayFinishedEntry.prototype = new OnGoingEntry;
  577. // empty job queue
  578. EventHandler.listen('taskqueue-updated', function () {
  579. if (TaskQueueUi.isEmpty) {
  580. var index = TWN.notifications.getIndex('noQueue');
  581. if (index != -1)
  582. TWN.notifications.playSound(TWN.notifications.list[index].sound);
  583. }
  584. });
  585. // new item in inventory
  586. TWN.appendFunction(['WestUi',
  587. 'showInventoryChanged'], function (type, item_id, count) {
  588. if (type == 'add') {
  589. var index = TWN.notifications.getIndex('newItem');
  590. if (index != -1)
  591. TWN.notifications.playSound(TWN.notifications.list[index].sound);
  592. }
  593. }, WestUi);
  594. // nickname in chat
  595. TWN.addListeners = function () {
  596. var roomChanged = function (room, type, data) {
  597. var index = TWN.notifications.getIndex('nickInChat');
  598. if (index != -1 && type == 'NewMessage') {
  599. var div = $(data[0]);
  600. var cText = div.find('.chat_text').html().toLowerCase();
  601. var nli = TWN.notifications.list[index];
  602. var nList = [Character.name];
  603. if (nli.info != '*')
  604. nList.push(...nli.info.split(';'));
  605. for (var n of nList)
  606. if (cText.includes(n.toLowerCase())) {
  607. TWN.notifications.playSound(nli.sound);
  608. break;
  609. }
  610. }
  611. };
  612. var rooms = Chat.Resource.Manager.getRooms();
  613. for (var r in rooms) {
  614. var room = Chat.Resource.Manager.getRoom(r);
  615. if (TWN.roomsListening.indexOf(room.id) == -1) {
  616. TWN.roomsListening.push(room.id);
  617. room.addListener(roomChanged);
  618. }
  619. }
  620. };
  621. if (EventHandler.hasOwnProperty('add')) {
  622. EventHandler.add('chat_room_added', function (room) {
  623. TWN.addListeners();
  624. });
  625. } else {
  626. EventHandler.listen('chat_room_added', function (room) {
  627. TWN.addListeners();
  628. });
  629. }
  630. },
  631. // Add notification
  632. add: function (event, info, sound) {
  633. TWN.set('notification_' + this.list.length, JSON.stringify({
  634. event: event,
  635. info: info,
  636. sound: sound
  637. }));
  638. this.list[this.list.length++] = {
  639. event: event,
  640. info: info,
  641. sound: sound
  642. };
  643. TWN.set('notificationCount', this.list.length);
  644. },
  645. // Remove specified notification
  646. remove: function (id) {
  647. for (var i = id; i < this.list.length; i++) {
  648. TWN.set('notification_' + i, TWN.get('notification_' + (i + 1), ''));
  649. this.list[i] = this.list[i + 1];
  650. }
  651. TWN.remove('notification_' + (--this.list.length));
  652. this.list[this.list.length] = {};
  653. TWN.set('notificationCount', this.list.length);
  654. },
  655. getIndex: function (event, info) {
  656. for (var i = 0; i < this.list.length; i++)
  657. if (this.list[i].event == event && (this.list[i].info == info || info == undefined))
  658. return i;
  659. return -1;
  660. },
  661. // Play the specified sound
  662. playSound: function (src) {
  663. if (src && $('#ui-loader').css('display') == 'none') {
  664. var audio = TWN.sounds.includes(src) ? 'https://tomrobert.safe-ws.de/' + src + '.mp3' : src;
  665. new Audio(audio).play();
  666. }
  667. }
  668. };
  669. TWN.settings = {
  670. gui: {
  671. window: {},
  672. comboboxes: {}
  673. },
  674. table: null,
  675. townforumTopics: {
  676. length: 0
  677. },
  678. init: function () {
  679. var rightBar = $('.ui_menucontainer');
  680. var optionEl = $('<div id="TWNotifierSettingsBtn" onclick="TWN.settings.open ();" title="' + TWN.name + '"></div>');
  681. if (rightBar && rightBar[1]) {
  682. rightBar = $(rightBar[1]);
  683. rightBar.css('max-height', (rightBar.children('div').length * 30 - 2) + 'px');
  684. rightBar.append(optionEl);
  685. }
  686. TWN.addStyle('#TWNotifierSettingsBtn { width:32px; height:41px; margin:-8px -16px 0 -7px; cursor:pointer; background:url(' + TWN.images.right_menu + '); }' +
  687. '#TWNotifierSettingsBtn:hover { background:url(' + TWN.images.right_menu_hover + '); }' +
  688. '.TWNotifier-event-col { min-width:175px; font-weight:bold; }' +
  689. '.TWNotifier-sound-col, .TWNotifier-remove-col { float:right; }' +
  690. '.TWNotifier-sound-col { margin-right:-2px; }' +
  691. '.TWNotifier-sound-col img, .TWNotifier-remove-col img { margin-top:-3px; cursor:pointer; }' +
  692. '.tbody .TWNotifier-event-col, .tbody .TWNotifier-info-col { margin-left:4px; }' +
  693. '.TWNotifierButton { background:rgba(29,28,28,0.5); border:1px solid #646464; border-radius:2px; box-shadow:0 0 1px 1px #000; display:inline-block; margin-left:8px; padding:1px 2px; }' +
  694. '.TWNotifierSettings #TWNotifierSettings { padding:4px 0 0 4px; border-top:1px solid rgba(0,0,0,0.77); margin:2px -2px; }' +
  695. '.TWNotifierSettings #reportWarning { margin:5px 5px 0 0; padding:5px 5px; display:none; border:1px solid #C33; }' +
  696. '.TWNotifierSettings .tfoot { padding:0 !important; height:6px; }' +
  697. '.TWNotifierSettings #settingInfo { margin:5px 5px 0 0; padding:5px 5px; text-align:center; border:1px solid #000; background:rgba(0,0,0,0.32); }' +
  698. '.TWNotifierSettings #settingInfo img { margin:0 16px; vertical-align:middle; }' +
  699. '.TWNotifierSettings #selectedForum { font-style:italic; }');
  700. },
  701. open: function () {
  702. this.gui.window = wman.open('TWNotifierSettings', TWN.name, 'noreload').setMiniTitle(TWN.name);
  703. TWN.settings.gui.window.showLoader();
  704. // Create table
  705. this.table = new west.gui.Table(false);
  706. this.table.addColumn('TWNotifier-event-col').addColumn('TWNotifier-info-col').addColumn('TWNotifier-remove-col').addColumn('TWNotifier-sound-col');
  707. this.table.appendToCell('head', 'TWNotifier-event-col', TWN.lang.event).appendToCell('head', 'TWNotifier-info-col', TWN.lang.info).appendToCell('head', 'TWNotifier-remove-col', '&nbsp;').appendToCell('head', 'TWNotifier-sound-col', '&nbsp;');
  708. this.table.setScrollbar();
  709. // Fill table
  710. TWN.settings.refreshTable();
  711. TWN.settings.gui.window.appendToContentPane(this.table.getMainDiv());
  712. // Create settings
  713. var settings = $('<div id="TWNotifierSettings"></div>');
  714. var dropdown = new west.gui.Combobox('TWNotifierNotificationType').setWidth(130).addListener(function () {
  715. TWN.settings.changeSettings(dropdown.getValue());
  716. });
  717. for (var type in TWN.lang.types)
  718. dropdown.addItem(type, TWN.lang.types[type]);
  719. // TODO: Correct width (depending on other elements)
  720. var soundName = new west.gui.Textfield('TWNotifierSoundName').setWidth(165).setPlaceholder('https:// .mp3');
  721. var soundBox = new west.gui.Combobox('TWNotifierSoundBox').setWidth(130);
  722. for (var sound of TWN.sounds)
  723. soundBox.addItem(sound, TWN.lang.sounds[sound]);
  724. soundBox.addItem('custom', TWN.lang.sounds.custom).addListener(function () {
  725. if (soundBox.getValue() == 'custom')
  726. soundName.getMainDiv().css('display', 'inline-block');
  727. else
  728. soundName.getMainDiv().css('display', 'none');
  729. });
  730. var testSound = $('<div class="TWNotifierButton" title="' + TWN.lang.listen + '"><img src="' + TWN.images.listen + '" style="cursor:pointer;"></div>').click(function () {
  731. if (soundBox.getValue() != 'custom')
  732. TWN.notifications.playSound(soundBox.getValue());
  733. else
  734. TWN.notifications.playSound(soundName.getValue());
  735. });
  736. var addButton = $('<div class="TWNotifierButton" title="' + TWN.lang.add + '"><img src="' + TWN.images.add + '" style="cursor:pointer;"></div>').click(function () {
  737. var event = dropdown.getValue();
  738. var info = TWN.settings.getInfo(event);
  739. var sound = soundBox.getValue();
  740. if (sound == 'custom')
  741. sound = soundName.getValue();
  742. TWN.notifications.add(event, info, sound);
  743. TWN.settings.refreshTable();
  744. });
  745. TWN.settings.gui.window.appendToContentPane($('<span>' + TWN.lang.event + ': </span>')).appendToContentPane(dropdown.getMainDiv()).appendToContentPane($('<span style="margin-left:8px;">' + TWN.lang.sound + ': </span>'));
  746. TWN.settings.gui.window.appendToContentPane(soundBox.getMainDiv()).appendToContentPane(soundName.getMainDiv().css({
  747. 'display': 'none',
  748. 'margin-top': '1px'
  749. })).appendToContentPane(testSound).appendToContentPane(addButton).appendToContentPane(settings);
  750. TWN.settings.changeSettings();
  751. TWN.settings.gui.window.hideLoader();
  752. },
  753. removeConfirmation: function (id) {
  754. var dialog = new west.gui.Dialog(TWN.lang.confirmationTitle, TWN.lang.confirmation);
  755. dialog.addButton('yes', function () {
  756. TWN.notifications.remove(id);
  757. $('.TWNotifierSettings .row_' + id).remove();
  758. TWN.settings.refreshTable();
  759. }).addButton('no', function () {
  760. dialog.hide();
  761. }).show();
  762. },
  763. refreshTable: function () {
  764. this.table.clearBody();
  765. for (var i = 0; i < TWN.notifications.list.length; i++) {
  766. var inl = TWN.notifications.list[i];
  767. var sound = inl.sound;
  768. this.table.appendRow(null, '');
  769. this.table.appendToCell(-1, 'TWNotifier-event-col', TWN.lang.desc[inl.event] || inl.event);
  770. this.table.appendToCell(-1, 'TWNotifier-info-col', TWN.settings.getDescription(inl));
  771. this.table.appendToCell(-1, 'TWNotifier-remove-col', $('<img src="' + TWN.images.remove + '" onclick="TWN.settings.removeConfirmation (' + i + ');" title="' + TWN.lang.remove + '">'));
  772. this.table.appendToCell(-1, 'TWNotifier-sound-col', $('<img src="' + TWN.images.sound + '" onclick="TWN.notifications.playSound(\'' + sound + '\');" title="' + TWN.lang.listen + '">'));
  773. }
  774. },
  775. changeSettings: function (val) {
  776. var settings = $('#TWNotifierSettings').html('');
  777. switch (val) {
  778. case ('friends'):
  779. settings.append($('<label for="friendsName" style="cursor:pointer;">' + TWN.lang.types.friends + ':</label>'), new west.gui.Textfield('friendsName').getMainDiv(), this.infoBox(val));
  780. break;
  781. case ('wayFinished'):
  782. settings.append(this.infoBox(val));
  783. break;
  784. case ('noQueue'):
  785. settings.append(this.infoBox(val));
  786. break;
  787. case ('townforum'):
  788. var dropdown = new west.gui.Combobox('TWNotifierTownforumTopic');
  789. $.ajax('forum.php', {
  790. complete: function (data) {
  791. var DOM = $.parseHTML(data.responseText);
  792. $('#forum_list', DOM).children('div').each(function (i, el) {
  793. if ($(el).find('span').text() == '')
  794. return;
  795. TWN.settings.townforumTopics[TWN.settings.townforumTopics.length] = $(el).find('span').text();
  796. TWN.settings.townforumTopics.length++;
  797. });
  798. dropdown.addListener(function () {
  799. $('#selectedForum').html((dropdown.getValue() != '*' ? ' ' + dropdown.getValue() : ''));
  800. });
  801. dropdown.addItem('*', TWN.lang.reportTypes.all);
  802. for (var i = 0; i < TWN.settings.townforumTopics.length; i++)
  803. dropdown.addItem(TWN.settings.townforumTopics[i], TWN.settings.townforumTopics[i]);
  804. TWN.settings.gui.comboboxes.townforumTopics = dropdown;
  805. settings.append($('<span>' + TWN.lang.types.townforum + ': </span>'), dropdown.getMainDiv(), TWN.settings.infoBox(val));
  806. }
  807. });
  808. break;
  809. case ('reports'):
  810. var dropdown = new west.gui.Combobox('TWNotifierReportType');
  811. var types = [
  812. 'all',
  813. 'work',
  814. 'duels',
  815. 'achvmnt',
  816. 'fort',
  817. 'other'
  818. ];
  819. for (var i = 0; i < types.length; i++)
  820. dropdown.addItem(types[i], TWN.lang.reportTypes[types[i]]);
  821. dropdown.addListener(function (selected) {
  822. if (selected != 'all')
  823. $('#reportWarning').css('display', 'block');
  824. else
  825. $('#reportWarning').css('display', 'none');
  826. });
  827. settings.append($('<span>' + TWN.lang.types.reports + ': </span>'), dropdown.getMainDiv(), $('<div id="reportWarning">' + TWN.lang.reportInfo + '</div>'));
  828. TWN.settings.gui.comboboxes.reportTypes = dropdown;
  829. break;
  830. case ('newItem'):
  831. settings.append(this.infoBox(val));
  832. break;
  833. case ('nickInChat'):
  834. settings.append($('<label for="TWNnicks" style="cursor:pointer;">' + TWN.lang.types.nickInChat + ':</label>'), new west.gui.Textfield('TWNnicks').getMainDiv(), this.infoBox(val));
  835. break;
  836. //case ('messages'):
  837. default:
  838. settings.append(this.infoBox('messages'));
  839. break;
  840. }
  841. },
  842. infoBox: function (text) {
  843. return $('<div id="settingInfo"><img src="' + TWN.images.info + '"> ' + TWN.lang[text + 'Info'] + ' <img src="' + TWN.images.info + '"></div>');
  844. },
  845. getInfo: function (i) {
  846. switch (i) {
  847. case ('reports'):
  848. return TWN.settings.gui.comboboxes.reportTypes.getValue() || 'all';
  849. case ('townforum'):
  850. return TWN.settings.gui.comboboxes.townforumTopics.getValue() || '*';
  851. case ('friends'):
  852. var fTF = $('#friendsName').val();
  853. return fTF ? fTF.replace(/;\s+/g, ';').replace(/;$/g, '') : '*';
  854. case ('nickInChat'):
  855. var nTF = $('#TWNnicks').val();
  856. return nTF ? nTF.replace(/;\s+/g, ';').replace(/;$/g, '') : '*';
  857. default:
  858. return '';
  859. }
  860. },
  861. getDescription: function (e) {
  862. var info = e.info;
  863. switch (e.event) {
  864. case ('reports'):
  865. return TWN.lang.reportTypes[info] || info;
  866. case ('townforum'):
  867. if (info == '*')
  868. return TWN.lang.reportTypes.all;
  869. return info;
  870. case ('friends'):
  871. if (info == '*')
  872. return TWN.lang.reportTypes.all;
  873. var res = '';
  874. info = info.split(';');
  875. for (var i = 0; i < info.length; i++) {
  876. if (i != 0 && info[i] != '')
  877. res += ', ';
  878. res += '<a href="javascript:PlayerProfileWindow.open (encodeURIComponent (\'' + info[i].replace(/'/g, '\\\'') + '\') );">' + info[i] + '</a>';
  879. }
  880. return res;
  881. case ('nickInChat'):
  882. var res = Character.name;
  883. if (info == '*')
  884. return res;
  885. info = info.split(';');
  886. for (var nick of info)
  887. res += ', ' + nick;
  888. return res;
  889. default:
  890. return TWN.lang[e.event + 'Info'];
  891. }
  892. },
  893. };
  894. (TWN.Updater = function () {
  895. if (!window.scriptRequest) {
  896. scriptRequest = true;
  897. $.getScript(TWN.updateUrl);
  898. }
  899. var intVal = setInterval(function () {
  900. if (window.scriptUp) {
  901. scriptUp.c('TWN', TWN.version, TWN.name, TWN.updateAd, TWN.website, TWN.LANGUAGE);
  902. clearInterval(intVal);
  903. }
  904. }, 2000);
  905. })();
  906. TWN.init();
  907. });