Compare commits
	
		
			1813 Commits
		
	
	
		
			v0.7.9
			...
			fix/databa
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | f419296cf5 | ||
|   | 65712776df | ||
|   | bde158e3d7 | ||
|   | 44110a9496 | ||
|   | 727f68a575 | ||
|   | 07fd034fe4 | ||
|   | 13ea68cc0c | ||
|   | 598cec2fe4 | ||
|   | 89fae38caa | ||
|   | 16849e7578 | ||
|   | 470555f268 | ||
|   | 7f60b3d31d | ||
|   | 12e40b2592 | ||
|   | 38902c30d1 | ||
|   | 3e61692780 | ||
|   | c88b08eb1e | ||
|   | 82d417b590 | ||
|   | b797908e49 | ||
|   | 90c8463797 | ||
|   | c91bb5d409 | ||
|   | fe821c5808 | ||
|   | 9acad15451 | ||
|   | 8c3cb0e06f | ||
|   | 2eae44e075 | ||
|   | 8272f1373c | ||
|   | 901df48d13 | ||
|   | 2da0024c68 | ||
|   | 0d8f68a48e | ||
|   | 0cb9d3a208 | ||
|   | d8b73f55a3 | ||
|   | 3bb272ebbb | ||
|   | 64acf70d38 | ||
|   | 97f9d3d6f6 | ||
|   | f54b1bdd2a | ||
|   | c898fe25ef | ||
|   | 73c07d470d | ||
|   | 56bd7ec5ed | ||
|   | 4c6277c124 | ||
|   | 228780f0ad | ||
|   | 4e9999cc0d | ||
|   | 8bc328d6fb | ||
|   | ac41b82579 | ||
|   | df7b6e29fb | ||
|   | e0cc19ad86 | ||
|   | 85e7005fd3 | ||
|   | 3c0cb53e17 | ||
|   | d0112d1a67 | ||
|   | ed9beaf2b6 | ||
|   | 5aa9bbf1c8 | ||
|   | a6032093b2 | ||
|   | 4eab805d26 | ||
|   | 3f24f961b1 | ||
|   | 0b86459940 | ||
|   | 7a9b11434e | ||
|   | 9725a3c2bd | ||
|   | 46adeefce3 | ||
|   | e4b66f34ac | ||
|   | 2465bb6f9a | ||
|   | 42671c5c19 | ||
|   | fec773ba4b | ||
|   | 1b9f68c9ec | ||
|   | 7a08f91d3f | ||
|   | 4b948e9510 | ||
|   | 17ca93d020 | ||
|   | bcc4b48eb0 | ||
|   | f8c4332e03 | ||
|   | 235e0f394d | ||
|   | 3451715e96 | ||
|   | d85681880e | ||
|   | 4701461b1f | ||
|   | 482f4067b2 | ||
|   | 2f26748112 | ||
|   | 98073a110a | ||
|   | 11dae90fa9 | ||
|   | 20f99903ae | ||
|   | b6e1620f14 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 9cb7792623 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 0db908be18 | ||
|   | 785d38312b | ||
|   | e1c04ed28e | ||
|   | c836308601 | ||
|   | 0efe47ce71 | ||
|   | 3b47e9df2f | ||
|   | 43415cf35d | ||
|   | cf7fd20452 | ||
|   | 080cc2781f | ||
|   | 20d69a641c | ||
|   | 2d4be327b2 | ||
|   | bb097b69ce | ||
|   | 6e5a4ff8c7 | ||
|   | caf326a658 | ||
|   | bccf8e056d | ||
|   | 7d27e5a0ba | ||
|   | 9b6f410459 | ||
|   | c06b0017f1 | ||
|   | d8132d4d76 | ||
|   | 1566deb84a | ||
|   | 536b29be95 | ||
|   | 5271633bdb | ||
|   | ce5b1cf2a6 | ||
|   | 83f84172e0 | ||
|   | 34fead906e | ||
|   | ec11c14024 | ||
|   | 2fe9924437 | ||
|   | f0f2e3785f | ||
|   | 36ca755243 | ||
|   | f17269e44c | ||
|   | dcb96f4ce1 | ||
|   | a89f9a8484 | ||
|   | 45d6047031 | ||
|   | c92148d467 | ||
|   | b4b62442fe | ||
|   | 047742848b | ||
|   | fe8281594e | ||
|   | 0bff910a05 | ||
|   | 6d43fc181f | ||
|   | 13d33822b5 | ||
|   | f78ebad136 | ||
|   | d90fa323d7 | ||
|   | 181131f7f3 | ||
|   | 0da524fefe | ||
|   | 6cf4b9dac5 | ||
|   | 5cfa3a697f | ||
|   | bb830bce44 | ||
|   | 566c2a9151 | ||
|   | 0f48f12e2e | ||
|   | 0ea247ce7e | ||
|   | b329da52aa | ||
|   | c720ccc451 | ||
|   | 8dc42b6544 | ||
|   | dca904e61d | ||
|   | 29faa4f695 | ||
|   | 4767120043 | ||
|   | 9a90e4aae2 | ||
|   | ba4ed6a04b | ||
|   | a7efacdbac | ||
|   | 577037becc | ||
|   | b8abc11b96 | ||
|   | 4def6a6cae | ||
|   | e6100a1b72 | ||
|   | 522f6c11d8 | ||
|   | 00c3635c5f | ||
|   | c074a48f24 | ||
|   | e222957893 | ||
|   | d423ddd07a | ||
|   | 4d4f7759d3 | ||
|   | 9510640ba9 | ||
|   | 98b13c91a4 | ||
|   | 0c95bcfd06 | ||
|   | 524e982a0e | ||
|   | fffb427eae | ||
|   | 10cd71a663 | ||
|   | 0812fe025d | ||
|   | 309c1fb715 | ||
|   | 8d29fdb98b | ||
|   | f782850307 | ||
|   | 835dda9659 | ||
|   | dcc703b1eb | ||
|   | 9d8e9d27bd | ||
|   | db09980de1 | ||
|   | 2dba778167 | ||
|   | ce2af2bb7a | ||
|   | dc839abfbb | ||
|   | 01d49692ed | ||
|   | de6603a513 | ||
|   | dd731fd49b | ||
|   | 064b929841 | ||
|   | c61747dc75 | ||
|   | 207d6bc691 | ||
|   | 8fdea94376 | ||
|   | c961a1ebf8 | ||
|   | 770ffcfc52 | ||
|   | 756d94bb3e | ||
|   | 6e0f591383 | ||
|   | fb91281140 | ||
|   | d8a6090be3 | ||
|   | 52109f5cca | ||
|   | 4b7b121550 | ||
|   | 28886551e8 | ||
|   | 7d435ff643 | ||
|   | ae847ff9a6 | ||
|   | 45ef390829 | ||
|   | 84d502bf10 | ||
|   | e776bd52be | ||
|   | 6e793390c6 | ||
|   | 6eda38603c | ||
|   | 72cdd290da | ||
|   | 40d65a6613 | ||
|   | 43153b2b0c | ||
|   | 2ea549002a | ||
|   | 4a30fb495d | ||
|   | 4d8f5f31ae | ||
|   | be7b27c31a | ||
|   | 7d213f479a | ||
|   | e574943707 | ||
|   | 1e9b10d648 | ||
|   | 7c92d1c197 | ||
|   | 3111d66df9 | ||
|   | e45dd88a93 | ||
|   | 5ed1aec28e | ||
|   | 7e4d28c648 | ||
|   | 3b2669fb3b | ||
|   | 6fe3bff163 | ||
|   | ae5be41e11 | ||
|   | 83a6f4b61d | ||
|   | ee360386d8 | ||
|   | bf06bed385 | ||
|   | 3949d84e5d | ||
|   | a161cff003 | ||
|   | 3befde2a1e | ||
|   | 5367df2381 | ||
|   | c48b800631 | ||
|   | ef6549c17c | ||
|   | 629fd18ea1 | ||
|   | da15105118 | ||
|   | 4ca58b4178 | ||
|   | 03e2752139 | ||
|   | 2fece725a4 | ||
|   | c24c580796 | ||
|   | 620a47da72 | ||
|   | 9b75011224 | ||
|   | 5b4b7b8a97 | ||
|   | 99997eb57d | ||
|   | 73a5829974 | ||
|   | 497338c2d6 | ||
|   | beb348fe27 | ||
|   | 5b1bd4f005 | ||
|   | f09606d01b | ||
|   | 67ab425bb9 | ||
|   | 113473f256 | ||
|   | d6ac4e8d85 | ||
|   | 6845869838 | ||
|   | 0fbd4bf1be | ||
|   | 1e45d5c393 | ||
|   | dbea69f314 | ||
|   | 4e6aa0f262 | ||
|   | fa1f927082 | ||
|   | de0512f11a | ||
|   | 93c09b3380 | ||
|   | d47195a787 | ||
|   | b618084d50 | ||
|   | d0d0af289d | ||
|   | 1d0c173e7d | ||
|   | 4e7c894cf2 | ||
|   | b71555d60d | ||
|   | c2bf94fb23 | ||
|   | 8cf3409077 | ||
|   | e0043b1300 | ||
|   | 86cb5821f6 | ||
|   | 82a533d88c | ||
|   | ceaa0639e6 | ||
|   | 6844f4392a | ||
|   | 6d8f4718a1 | ||
|   | f40b986b59 | ||
|   | 190697ce98 | ||
|   | 64f6d3abca | ||
|   | e6f05a2731 | ||
|   | 6a0356aa0f | ||
|   | 50d649dbde | ||
|   | 6c568fd36a | ||
|   | fa6b6aa153 | ||
|   | ae639d65b0 | ||
|   | 35e2483de8 | ||
|   | bbf923e1a6 | ||
|   | 211b6ea698 | ||
|   | 6d156ae080 | ||
|   | a5b3940e59 | ||
|   | dbf73d0b61 | ||
|   | 65696f63e3 | ||
|   | 6341093578 | ||
|   | d25c71857f | ||
|   | 7dcb5c4a1f | ||
|   | ff1723b756 | ||
|   | 1a5771ad51 | ||
|   | 6fac883659 | ||
|   | 4a6896b446 | ||
|   | 0852fba6f0 | ||
|   | 9239a4f419 | ||
|   | 00fe1adc15 | ||
|   | c2f55791c0 | ||
|   | 464492d826 | ||
|   | 887b5068ad | ||
|   | 4c5cc8b573 | ||
|   | 529bdcf016 | ||
|   | 3e3f4bb5a5 | ||
|   | aa52df6e2e | ||
|   | 3b31915c22 | ||
|   | 1c6cda4df9 | ||
|   | cf51f7aa8d | ||
|   | ed89b99cd1 | ||
|   | 9d7fc98e1e | ||
|   | f646856e20 | ||
|   | f97f8cbe87 | ||
|   | 3da3e62c5b | ||
|   | d5dd7297b5 | ||
|   | 73de93a561 | ||
|   | ae1161d770 | ||
|   | 4455964db4 | ||
|   | 84870dbf2d | ||
|   | 329153fda6 | ||
|   | 4b6024dc45 | ||
|   | 28fef952f8 | ||
|   | 4fda4f643b | ||
|   | 19686725dc | ||
|   | a73fb1003e | ||
|   | b46ddb43d0 | ||
|   | de468a8dcd | ||
|   | ea51ad27c3 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | d2a4748a59 | ||
|   | a1ed209591 | ||
|   | 34321613d6 | ||
|   | 19b290feb7 | ||
|   | 9ab25abcdf | ||
|   | ea753278a0 | ||
|   | 4d749b8815 | ||
|   | 07012f786b | ||
|   | a45ceab83a | ||
|   | 669c447fca | ||
|   | da43b32ff0 | ||
|   | cbe0d187b4 | ||
|   | c5d5bb8067 | ||
|   | e85ce193be | ||
|   | 3fb2675b5a | ||
|   | b7de8b32eb | ||
|   | 89be68731e | ||
|   | 10dd818b13 | ||
|   | 13a1598a46 | ||
|   | 4f6178eca0 | ||
|   | dc2b5afd99 | ||
|   | 11cee81c5f | ||
|   | d639e77d04 | ||
|   | dd47423157 | ||
|   | b02c7f4239 | ||
|   | b5b2e3fd78 | ||
|   | 030d15f0cd | ||
|   | b6b7592226 | ||
|   | fb10741a02 | ||
|   | 5e9c868dfa | ||
|   | 0904b1bb87 | ||
|   | faa60f5e9a | ||
|   | 620e0f62e4 | ||
|   | 2ae2ec3353 | ||
|   | b323d9cee1 | ||
|   | 4f1d1d8043 | ||
|   | 8e5a3afc6e | ||
|   | a7311301e2 | ||
|   | ac10236154 | ||
|   | dc95bc4bad | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 0dc7da472f | ||
|   | 43421e56ea | ||
|   | 544d006b6f | ||
|   | 085ebbcfde | ||
|   | 77a2c1cec3 | ||
|   | e918591666 | ||
|   | 175c2a1f89 | ||
|   | 3b5be1a8db | ||
|   | c769962e39 | ||
|   | 35dfaa28ed | ||
|   | 8e501c0e9c | ||
|   | c52ca27126 | ||
|   | 41a3cb6f42 | ||
|   | eb4b3ada49 | ||
|   | 68bdec7c18 | ||
|   | 8a612429b2 | ||
|   | 16671ea40b | ||
|   | 8fb643596f | ||
|   | c2b7286d20 | ||
|   | d6c40c836a | ||
|   | 99262c3ebd | ||
|   | b8396d4c84 | ||
|   | b0c8cf2ecd | ||
|   | da1816cc13 | ||
|   | 783d96fc65 | ||
|   | 988a3f2dbe | ||
|   | 8e0978c1ed | ||
|   | 023f1dc598 | ||
|   | ea5e1d4192 | ||
|   | 06188be6e1 | ||
|   | 2c42de688a | ||
|   | 4ac56e6b15 | ||
|   | 5e60249603 | ||
|   | d8b6b749ee | ||
|   | c5e114d550 | ||
|   | 706fca8868 | ||
|   | 65adf9ccdd | ||
|   | bc6663dc44 | ||
|   | e3ffe5d9e1 | ||
|   | c0a66037e0 | ||
|   | 17210b717f | ||
|   | 5782772b90 | ||
|   | 27c44f1bdf | ||
|   | 3f6ff3a332 | ||
|   | 79636280a7 | ||
|   | 38e699ba4b | ||
|   | afb055f2dc | ||
|   | 6f58df0467 | ||
|   | 95343cec02 | ||
|   | 8055785c81 | ||
|   | 64e4c08950 | ||
|   | 12d8faa3ed | ||
|   | 1e6892971b | ||
|   | 8ae22accc9 | ||
|   | a2fadc5945 | ||
|   | d0b4065ccf | ||
|   | 84d37c5a8f | ||
|   | 28a2b34cc1 | ||
|   | bab565fbd0 | ||
|   | 36bd3eb846 | ||
|   | 85bc2342cf | ||
|   | 507402171b | ||
|   | 941846605c | ||
|   | a4a2480995 | ||
|   | ddced132cf | ||
|   | 749e8e6f02 | ||
|   | 7d787b4566 | ||
|   | 7e67e11e16 | ||
|   | 011a85d8ae | ||
|   | 382f897322 | ||
|   | c980a09146 | ||
|   | 18bd325a44 | ||
|   | 078e20a9a4 | ||
|   | e96227fbe4 | ||
|   | c49c9d99a9 | ||
|   | a0f1971583 | ||
|   | cb5fc84e2e | ||
|   | 29b77035be | ||
|   | b8c0215720 | ||
|   | 3100faa645 | ||
|   | f7c9a67a96 | ||
|   | e8fedb8d16 | ||
|   | 4e4739e8ab | ||
|   | c6cc84a668 | ||
|   | 95a7c23a70 | ||
|   | a7fe400614 | ||
|   | 2568046a4d | ||
|   | 7161678c4b | ||
|   | 93641fc68a | ||
|   | ea7e808508 | ||
|   | da3fc1fc8c | ||
|   | 201f95caa8 | ||
|   | 779aa152fa | ||
|   | d99b22f98b | ||
|   | 35e28350bd | ||
|   | 327dcb5f87 | ||
|   | bc8ada6fe2 | ||
|   | 6183b7ee52 | ||
|   | 760c3ab017 | ||
|   | ab73d60c61 | ||
|   | 8d8bdb6dac | ||
|   | 71c00aa5e0 | ||
|   | 1fcdd54c94 | ||
|   | c2ec468246 | ||
|   | 68118fb7c2 | ||
|   | 5a69b9a802 | ||
|   | 45e63b13c3 | ||
|   | 758a8b3330 | ||
|   | 1843728930 | ||
|   | cff62ccba4 | ||
|   | 28f98db9de | ||
|   | da14e125e9 | ||
|   | cd49dfc799 | ||
|   | ef79b99b8a | ||
|   | 9a27403e7d | ||
|   | 5f63c3b227 | ||
|   | 203e411b62 | ||
|   | fcb13f3c0f | ||
|   | d94828772c | ||
|   | 10a739773c | ||
|   | 83b3dc803a | ||
|   | 33a47137c9 | ||
|   | dc17b701da | ||
|   | d30811404b | ||
|   | a631760dbf | ||
|   | bc3dcab462 | ||
|   | a8d255c04b | ||
|   | 813786c768 | ||
|   | 0db0ec1aa4 | ||
|   | bdc0c43d3f | ||
|   | c7a6a539a9 | ||
|   | c1d4b4f80c | ||
|   | 47a19e85dd | ||
|   | d9c1b2507c | ||
|   | 4c0739d3e9 | ||
|   | afe70a03c5 | ||
|   | 3fadf87a7a | ||
|   | c24576165c | ||
|   | 1e5c9dcd9b | ||
|   | a04d186c22 | ||
|   | 42f99c3edc | ||
|   | 4f4965369d | ||
|   | 57b47ab798 | ||
|   | 9ea2a5067f | ||
|   | ec96985872 | ||
|   | 9f2a51b351 | ||
|   | a1d7c94166 | ||
|   | 0c3e3e16dd | ||
|   | 45dda5e834 | ||
|   | 32ae4dde20 | ||
|   | d3f03fa735 | ||
|   | 44eff8092c | ||
|   | 8ef3d06f1e | ||
|   | 60bd64a639 | ||
|   | a1bcb217ec | ||
|   | 933b681a9f | ||
|   | e9aea17e1b | ||
|   | 060400b074 | ||
|   | 6be4a42c5a | ||
|   | 1e8198635e | ||
|   | be78a0fc45 | ||
|   | 08ac8ebade | ||
|   | 66ecc487a1 | ||
|   | 9e23ec6745 | ||
|   | 968899ef77 | ||
|   | 3844ad0d71 | ||
|   | c93bf5a984 | ||
|   | 50336a810b | ||
|   | 48f6ca0eba | ||
|   | 30107222d4 | ||
|   | f92b275f70 | ||
|   | 504242fb84 | ||
|   | e2bab4220b | ||
|   | 0b4c34a823 | ||
|   | c5aa9a4684 | ||
|   | 301afe190b | ||
|   | c35cc83e4f | ||
|   | 3ba9d8f780 | ||
|   | 06f228509b | ||
|   | 39e682dfd2 | ||
|   | 6f209440e0 | ||
|   | b2a1675de3 | ||
|   | 163877d303 | ||
|   | a4d11c1a12 | ||
|   | 8cf4e3da02 | ||
|   | e0230c5237 | ||
|   | 127e03081c | ||
|   | e9c6017e60 | ||
|   | d5915df37e | ||
|   | eb0c2a7674 | ||
|   | d225c2da26 | ||
|   | d95e280b9a | ||
|   | 64387e085b | ||
|   | e1f507cf2d | ||
|   | c92a410209 | ||
|   | 1186f94e21 | ||
|   | f837b3133d | ||
|   | 9106f1e4ce | ||
|   | a62cfc5272 | ||
|   | 6229736d07 | ||
|   | 6807339056 | ||
|   | ffaa0729ac | ||
|   | 03cc09b8c7 | ||
|   | 6d4724f4f4 | ||
|   | 2afe0c1185 | ||
|   | 6334f3f4fa | ||
|   | fe7ad61abe | ||
|   | e23a749e4c | ||
|   | ab5e4eff76 | ||
|   | fdd3bfd105 | ||
|   | 93ad347571 | ||
|   | 7d4aafda4f | ||
|   | 87e8c9eb4d | ||
|   | d61197b6a1 | ||
|   | dfba8bc60b | ||
|   | d2d497d82c | ||
|   | 4204e0a419 | ||
|   | e8e093cc1f | ||
|   | 2b39a1e406 | ||
|   | cac592e63a | ||
|   | 0255d0bef2 | ||
|   | a59f0e9244 | ||
|   | 9f3231fff6 | ||
|   | 647eae08b4 | ||
|   | e2487f97e3 | ||
|   | 235e69b8da | ||
|   | 649e37ab0f | ||
|   | dff4a98ef5 | ||
|   | b754374585 | ||
|   | ad789c50ff | ||
|   | ccfd2b4f55 | ||
|   | 3f5744964a | ||
|   | b22dc0014a | ||
|   | 00cbce20b0 | ||
|   | bbe922a65d | ||
|   | 8f23c62708 | ||
|   | 58bb6093b0 | ||
|   | 2faaa037ab | ||
|   | cc9057324a | ||
|   | f7971a21d8 | ||
|   | 08e7cf05b5 | ||
|   | 2e482fdc2a | ||
|   | a2c8e2b2ae | ||
|   | cc3e66cacb | ||
|   | bd86454fea | ||
|   | 1bb6e61583 | ||
|   | 13a2570ad0 | ||
|   | e961f2efcf | ||
|   | 54609bf90e | ||
|   | 6494bd2c0c | ||
|   | 670812772d | ||
|   | ae8a9fc44c | ||
|   | f80c5fd8ed | ||
|   | 6bac02bd35 | ||
|   | ac67555f28 | ||
|   | 6c4fd4ed27 | ||
|   | a8a896e0f5 | ||
|   | b517a12f8a | ||
|   | 5d741944f7 | ||
|   | a3056f5f48 | ||
|   | 8518f21987 | ||
|   | a3a2f05783 | ||
|   | 9f3c980ed2 | ||
|   | 31f8c99745 | ||
|   | 25c0bac7a3 | ||
|   | 9a749afc46 | ||
|   | 87df817eae | ||
|   | 3a58c8a6f9 | ||
|   | 2ba03e0c99 | ||
|   | f7f46bae00 | ||
|   | ccc91a473c | ||
|   | 7e347e950f | ||
|   | 535ae2047d | ||
|   | 12bc6a0333 | ||
|   | 3a86738983 | ||
|   | 3b3e9b0e70 | ||
|   | 54b9cc5402 | ||
|   | 6d23b285c1 | ||
|   | 76256a7ee6 | ||
|   | 07dafc5118 | ||
|   | b5c1b431d5 | ||
|   | 3a3e434d4e | ||
|   | d71bab648d | ||
|   | 3554b41172 | ||
|   | 41022727bd | ||
|   | 9b781d09a9 | ||
|   | c8d4e7d186 | ||
|   | 6cd8b7697d | ||
|   | 19c4cb810b | ||
|   | ba6119e6d0 | ||
|   | 1ce816040a | ||
|   | aa8e26f6a3 | ||
|   | f0eb113bc2 | ||
|   | 6ed8f18115 | ||
|   | 2262c4e882 | ||
|   | 69b02fa977 | ||
|   | 6baf49bba8 | ||
|   | bb02328b5a | ||
|   | 5a4854c205 | ||
|   | c661ae36ef | ||
|   | df8fb68d5e | ||
|   | fb0afdcea1 | ||
|   | e3775fed86 | ||
|   | 93b0d3829d | ||
|   | b6f98ffdee | ||
|   | 511e10e78b | ||
|   | cfdbc2a8b2 | ||
|   | 1a6fb8bee2 | ||
|   | 410d75c882 | ||
|   | c59bacea93 | ||
|   | f719c02050 | ||
|   | 0698e7b5f5 | ||
|   | c594dfd14b | ||
|   | 514c4a037a | ||
|   | b894f75e74 | ||
|   | d2a3a9a8da | ||
|   | 3f4c02a327 | ||
|   | 199672e0c8 | ||
|   | 02adb87fac | ||
|   | b4448f7279 | ||
|   | 687c9a6690 | ||
|   | 2b86ba94fe | ||
|   | a9fb5dffa3 | ||
|   | da77ec20ef | ||
|   | 6fd141eca6 | ||
|   | e17dde0dca | ||
|   | d1046ba21d | ||
|   | 98332f1483 | ||
|   | 1423046039 | ||
|   | 9c60beeed0 | ||
|   | 336b6ac530 | ||
|   | c71722fc52 | ||
|   | 4d8d574089 | ||
|   | e74fbe5bfd | ||
|   | 48e9a1ed51 | ||
|   | 56631bdf27 | ||
|   | b1224d9d1a | ||
|   | e18ada3d9d | ||
|   | c8218f69a5 | ||
|   | f991a8c817 | ||
|   | 36ec2e1e56 | ||
|   | 19c06df300 | ||
|   | b2d5d6f115 | ||
|   | 5769ac8bb4 | ||
|   | 41c9f54e4b | ||
|   | 8ef238c96c | ||
|   | 9ffb7f5fa9 | ||
|   | 8b5464f8f8 | ||
|   | f008591580 | ||
|   | 1d5b751fe1 | ||
|   | 37bde7df22 | ||
|   | 89deca1adb | ||
|   | c996f25d8d | ||
|   | d291f694d2 | ||
|   | cee1e67d3d | ||
|   | c81861d8c8 | ||
|   | c3c1a6b2a6 | ||
|   | d0590d2747 | ||
|   | c79a1d5f3a | ||
|   | ada1e391d4 | ||
|   | 193e18523d | ||
|   | 3fb9b1ae2f | ||
|   | 561bdcd766 | ||
|   | 556ef47d59 | ||
|   | 130ad25c4d | ||
|   | 08bea2c541 | ||
|   | 8974830621 | ||
|   | d582120fac | ||
|   | 8227303b89 | ||
|   | 7a402ec0e0 | ||
|   | 790d85a88a | ||
|   | a04fbde607 | ||
|   | 9d119b6279 | ||
|   | 7dd9b7764a | ||
|   | 3297a7c51a | ||
|   | 4a430ae9db | ||
|   | 26a80e0741 | ||
|   | 3b9feaf3bd | ||
|   | 21bff97137 | ||
|   | a2a273cde2 | ||
|   | fc5635bad3 | ||
|   | e01a44f352 | ||
|   | 855b05b15f | ||
|   | b3991a8e78 | ||
|   | 0ac0f4e7a8 | ||
|   | e9f155fb49 | ||
|   | 55b5e3b600 | ||
|   | 08339fe8b6 | ||
|   | 89c2e84bff | ||
|   | f76615e59b | ||
|   | 4c4089a155 | ||
|   | 2d02d8d8b3 | ||
|   | 95b1460b13 | ||
|   | 673e40350a | ||
|   | f7cbe5170d | ||
|   | 619b8ba4a0 | ||
|   | 8c3b73ca9e | ||
|   | d90810cf84 | ||
|   | fd25e6e881 | ||
|   | 63e69c97b7 | ||
|   | 574e35ba35 | ||
|   | 09627bdb1e | ||
|   | 5f10773189 | ||
|   | 8a3986932d | ||
|   | 9e2a87f448 | ||
|   | 0746708743 | ||
|   | 3ef53aff6c | ||
|   | f43a5d1221 | ||
|   | 43353b4f53 | ||
|   | a692607c5e | ||
|   | b72e7a3d96 | ||
|   | e15b57f967 | ||
|   | c3a161e2ee | ||
|   | 30fe42939d | ||
|   | 627369bbde | ||
|   | 7cea023965 | ||
|   | eb416e18cc | ||
|   | fc0d13437a | ||
|   | 14c8160020 | ||
|   | 1f95a415aa | ||
|   | 370cc554ad | ||
|   | 2991696a60 | ||
|   | a1ecdd228d | ||
|   | 6c8961638e | ||
|   | 3dd493b790 | ||
|   | b49c247162 | ||
|   | cfbcabbfdb | ||
|   | 0f38a677b1 | ||
|   | 0835b69a93 | ||
|   | 538723c405 | ||
|   | 4f2e410a71 | ||
|   | a70daa8830 | ||
|   | ae600da28b | ||
|   | d8f1bf0a50 | ||
|   | cfc4f3601b | ||
|   | 1a533388e7 | ||
|   | 98335b8cc0 | ||
|   | 16ebc1f577 | ||
|   | 7bab8f033c | ||
|   | 42d97721bf | ||
|   | 23266e05ed | ||
|   | a72d1a3c9f | ||
|   | c802d427eb | ||
|   | aacc120360 | ||
|   | 757ec28028 | ||
|   | 41fa695d8b | ||
|   | b12c30982d | ||
|   | fcb2fc3002 | ||
|   | bb0e621308 | ||
|   | 53221a9fd1 | ||
|   | d3b15a0a3e | ||
|   | 23047aa608 | ||
|   | beff3e3aa6 | ||
|   | 4a629b4418 | ||
|   | 3c3ddc4578 | ||
|   | 0788dc8848 | ||
|   | 5791d1e7f9 | ||
|   | a9cb017def | ||
|   | eaa9d6be43 | ||
|   | 7588904372 | ||
|   | 712ca30293 | ||
|   | 5fa4890b70 | ||
|   | ca56b4f101 | ||
|   | 707aea18db | ||
|   | 848c5c0887 | ||
|   | e14df529c0 | ||
|   | 9f67cab503 | ||
|   | 99c53c75f2 | ||
|   | df7c82c571 | ||
|   | ddb093ec48 | ||
|   | 714476bf29 | ||
|   | e49690b52b | ||
|   | f9d35b719b | ||
|   | a61cd43c3c | ||
|   | 6d1b3235d2 | ||
|   | e7e9d8e3b9 | ||
|   | 8cf0e80019 | ||
|   | c392fa7272 | ||
|   | 082884baa0 | ||
|   | 3a31a0326c | ||
|   | 2d561f267d | ||
|   | 5eafff737a | ||
|   | 8cf4d0cb0f | ||
|   | d1953470d9 | ||
|   | 3a52f2c403 | ||
|   | ac40922957 | ||
|   | 5aed9ee1a4 | ||
|   | 8318169c39 | ||
|   | ad00cf3fc3 | ||
|   | 3ff7b21287 | ||
|   | 36fbae850d | ||
|   | 24ff5684cd | ||
|   | aab62fb724 | ||
|   | a810890614 | ||
|   | a3bfdc1ec8 | ||
|   | a7dc719934 | ||
|   | 74433303fb | ||
|   | 30d62bda3b | ||
|   | cc7703766e | ||
|   | 9d664d3577 | ||
|   | 76bfab1303 | ||
|   | 7d2fc48437 | ||
|   | 171c114b0f | ||
|   | b1d2ac34a2 | ||
|   | c7ce87c4b6 | ||
|   | 4e22c42b10 | ||
|   | eabe789bbb | ||
|   | aa1403480c | ||
|   | 91c8f1f5bc | ||
|   | b421bf3931 | ||
|   | 6e6f4679f4 | ||
|   | 5bb3e57b7b | ||
|   | 17221f5369 | ||
|   | 98d4d3fcf0 | ||
|   | 82092338d6 | ||
|   | 9868b41a61 | ||
|   | c247789adf | ||
|   | 48822b6561 | ||
|   | cd22f8def5 | ||
|   | 0f30ebbcea | ||
|   | 1a2e46f09b | ||
|   | 52ac011556 | ||
|   | f34e5f2ac0 | ||
|   | ca8db22639 | ||
|   | 1846bf5255 | ||
|   | dce0ac2f8f | ||
|   | 9cc60983d0 | ||
|   | 7c2c88f780 | ||
|   | 7690811da3 | ||
|   | 7dc2e404ed | ||
|   | 080ab56ea9 | ||
|   | 83915f080c | ||
|   | 2841f17729 | ||
|   | 0187ba4938 | ||
|   | bedfc0a2e0 | ||
|   | ea08c04963 | ||
|   | 067f2af3e5 | ||
|   | 8d98306f8e | ||
|   | 09a045334c | ||
|   | bc8e5fc144 | ||
|   | 77e0d28a9d | ||
|   | 480a054f0c | ||
|   | 26c895d475 | ||
|   | 5cbb55cfb1 | ||
|   | dcb9506a1b | ||
|   | 2acec4df12 | ||
|   | 4bd761c726 | ||
|   | 2f732b8411 | ||
|   | 5aa02055bf | ||
|   | 6ed15565c8 | ||
|   | 77a2c55c87 | ||
|   | 4a9fa01eb7 | ||
|   | bd031d8980 | ||
|   | b76a037a94 | ||
|   | e71daa2520 | ||
|   | f372aeb067 | ||
|   | ef37bbcb81 | ||
|   | 944457463e | ||
|   | 6f7f25bb46 | ||
|   | d60d7f2250 | ||
|   | 2b8c4b3eca | ||
|   | 7039bda359 | ||
|   | d346a8f73f | ||
|   | 523f2dee7c | ||
|   | b33e39491b | ||
|   | 317ebf4387 | ||
|   | 31ba780099 | ||
|   | d1b30619e2 | ||
|   | 3fab52296a | ||
|   | a6e109799a | ||
|   | 80af2cd691 | ||
|   | d911b55e25 | ||
|   | eb73fc4538 | ||
|   | 75f77ec7a3 | ||
|   | a1d969bbfd | ||
|   | 11f1ad6d76 | ||
|   | 7facf0adad | ||
|   | 2b739c2b40 | ||
|   | 269ae323e0 | ||
|   | 0d0e5812dd | ||
|   | 61c2661377 | ||
|   | de710dff94 | ||
|   | 8c524171fb | ||
|   | 946d24690c | ||
|   | bf137189c5 | ||
|   | da4e18cb69 | ||
|   | 85769c1439 | ||
|   | 4d3ad4b6b9 | ||
|   | e900a62e75 | ||
|   | c3969364aa | ||
|   | e9df9f10dc | ||
|   | f78f5b5361 | ||
|   | c061438a35 | ||
|   | 8441dbe007 | ||
|   | e21a741a78 | ||
|   | 955f437e6c | ||
|   | fd419076c2 | ||
|   | 7569536d56 | ||
|   | 3a6102900f | ||
|   | 6dbc694409 | ||
|   | 7a3dcc4dc6 | ||
|   | 23393b5d3e | ||
|   | 863f3ad510 | ||
|   | e6d86ca280 | ||
|   | c22e25e3d2 | ||
|   | 52ffb195ec | ||
|   | 92a51af638 | ||
|   | d7a9158cf2 | ||
|   | f0f84090d2 | ||
|   | 9d78a3b5cf | ||
|   | 2fc163af5a | ||
|   | 10be98e371 | ||
|   | e0eb083e44 | ||
|   | e17cd78153 | ||
|   | 0015f511f8 | ||
|   | f0f71c9f85 | ||
|   | 0002543cca | ||
|   | c1096415aa | ||
|   | 6625768228 | ||
|   | a27f601fe8 | ||
|   | 72a877d9ca | ||
|   | b7ba09a551 | ||
|   | a98cb66c53 | ||
|   | 6785ecad1d | ||
|   | 937af536b6 | ||
|   | 5487314230 | ||
|   | 51e9bb2a7f | ||
|   | 376bb981ae | ||
|   | ed9d78d2f3 | ||
|   | 3c4e50dbda | ||
|   | 523f9dd95a | ||
|   | a43742c8b1 | ||
|   | c49e4fd63d | ||
|   | 905cce7021 | ||
|   | 7a49b5dedc | ||
|   | 3a2870a6bb | ||
|   | 9a475f2c57 | ||
|   | 58598742e8 | ||
|   | d04e44f52f | ||
|   | c7ec1f44e9 | ||
|   | 3ed9a5d3d8 | ||
|   | 61285b6b8c | ||
|   | d17c547bca | ||
|   | 7bc20b0993 | ||
|   | 6c4b3dea96 | ||
|   | 6ae1bf5814 | ||
|   | 8503135ce0 | ||
|   | 590fe0762d | ||
|   | d565b90736 | ||
|   | c88156802a | ||
|   | 7d8dbcbde7 | ||
|   | 66ec66b291 | ||
|   | fc0eb0e793 | ||
|   | ed7e9e1eae | ||
|   | 8985917a96 | ||
|   | 3a3411c117 | ||
|   | 1166ddfe87 | ||
|   | 574e361f90 | ||
|   | f3745a2752 | ||
|   | a2fb9a183b | ||
|   | 295c5de0d6 | ||
|   | d4650afa0e | ||
|   | 07da4ca028 | ||
|   | feffdd1837 | ||
|   | 979532d3df | ||
|   | 3c77c54c8e | ||
|   | 74d013049d | ||
|   | 708aa2d72f | ||
|   | dd6581f7f7 | ||
|   | 8c801dddec | ||
|   | 9de8145f82 | ||
|   | 77460b0832 | ||
|   | 1fb1fb3ae9 | ||
|   | 1d1e927d56 | ||
|   | 036abf83e5 | ||
|   | e737cf612c | ||
|   | 78622fb47a | ||
|   | 9560494ab0 | ||
|   | 8aac3ec2e5 | ||
|   | 269ca501f1 | ||
|   | 20638f430a | ||
|   | acb551c5b0 | ||
|   | 44a6400fcf | ||
|   | 847c3db625 | ||
|   | f30181d485 | ||
|   | 118e8c487e | ||
|   | c73e476e88 | ||
|   | ac5b864ea9 | ||
|   | 42d531838c | ||
|   | 2321cf84b0 | ||
|   | a570363fe0 | ||
|   | 616b8eb61a | ||
|   | e1d486c8c8 | ||
|   | b841c9f631 | ||
|   | e6c72efd18 | ||
|   | 9693fd260c | ||
|   | 717b5fdd15 | ||
|   | 32cf487128 | ||
|   | a9941dea8a | ||
|   | 5c9737f281 | ||
|   | 87a98531d9 | ||
|   | 6d142dcbfe | ||
|   | 90f00e9960 | ||
|   | 8711e178e9 | ||
|   | eb28b38709 | ||
|   | afea618867 | ||
|   | 0abb9384a6 | ||
|   | 2563583f84 | ||
|   | 6acbbe3fa1 | ||
|   | 6c157f3f6c | ||
|   | c4737eca72 | ||
|   | 5428f5e2cf | ||
|   | 7d6d77cfbc | ||
|   | 87eacd17c5 | ||
|   | dd4420dcfd | ||
|   | b8843a29eb | ||
|   | a12262df55 | ||
|   | 091828e8f1 | ||
|   | 8bca099037 | ||
|   | a43d641b5f | ||
|   | 46c058df25 | ||
|   | fa7c6497e6 | ||
|   | 82b41d4df5 | ||
|   | fd2c2d552a | ||
|   | 78ae456b45 | ||
|   | 7e5528b7e1 | ||
|   | a97f55e189 | ||
|   | 50dd65c6de | ||
|   | 16aeb12111 | ||
|   | 96a7c43cb5 | ||
|   | ee20ee2ecd | ||
|   | efdd156d5e | ||
|   | be41023005 | ||
|   | d143f05bb1 | ||
|   | fdc229b196 | ||
|   | f6a5552296 | ||
|   | 62a4b4d3ec | ||
|   | ef24d6739a | ||
|   | 1831198349 | ||
|   | ddf764e308 | ||
|   | 988c757ca6 | ||
|   | cedcd14550 | ||
|   | 0ff290f868 | ||
|   | 1764ce0519 | ||
|   | f3b49d7cba | ||
|   | 6d19d69d20 | ||
|   | 9ad367370a | ||
|   | eb091e487d | ||
|   | a5ccc794bc | ||
|   | 1427dc3ede | ||
|   | e47bb11883 | ||
|   | 6f3ba9c34b | ||
|   | 0f3d2424ce | ||
|   | 8ecd8a10c0 | ||
|   | 3cc3e3a8e9 | ||
|   | be1086bcba | ||
|   | f9abe9a8e3 | ||
|   | 632ecb6d20 | ||
|   | db554df041 | ||
|   | 7300e4f1ad | ||
|   | 9b84532e57 | ||
|   | 14870d74df | ||
|   | 9c7794fe13 | ||
|   | d9526d4021 | ||
|   | 454e09ec3d | ||
|   | c687f64ced | ||
|   | 80623580f2 | ||
|   | 135f393fc4 | ||
|   | e03da2876c | ||
|   | 44fff9dcd1 | ||
|   | 02f993baea | ||
|   | f9302d4f9d | ||
|   | 780f8d193f | ||
|   | 4e85f857a4 | ||
|   | ea035136e1 | ||
|   | 9d8f398d9f | ||
|   | 31f0050f4e | ||
|   | 7ce005341e | ||
|   | 84447ef178 | ||
|   | b99d3b4960 | ||
|   | 0fc64478e0 | ||
|   | e7a3d563aa | ||
|   | bda020ef93 | ||
|   | f0c136c421 | ||
|   | 5fa1321619 | ||
|   | 792ec17d18 | ||
|   | 19ffd57b34 | ||
|   | ebda456862 | ||
|   | 5bd5aa0edf | ||
|   | 6b07d56627 | ||
|   | 15d381adfd | ||
|   | 23b44d6c8a | ||
|   | e3f2abc06e | ||
|   | 3d73de13d8 | ||
|   | 71f7bb2e75 | ||
|   | ebe900fca8 | ||
|   | 5a8bcec014 | ||
|   | a1c7c2768c | ||
|   | 565e6e3a3d | ||
|   | 855e9aa3b9 | ||
|   | a271edec47 | ||
|   | 81b293a5a6 | ||
|   | 8b41e144f8 | ||
|   | a41f653e05 | ||
|   | f24ff295e8 | ||
|   | b399bee3ac | ||
|   | 8f88c82a13 | ||
|   | d8ac88b7d9 | ||
|   | 443c5a80b4 | ||
|   | ba56ef5e33 | ||
|   | b24370e7ed | ||
|   | b2b0b31168 | ||
|   | 1e969f8d8a | ||
|   | bca098e074 | ||
|   | 98bd51436b | ||
|   | 1fa4b1e660 | ||
|   | 04a36b1d11 | ||
|   | 611d6f505d | ||
|   | 62b485abf9 | ||
|   | 61eae7d7c4 | ||
|   | af161b5143 | ||
|   | d5880eac8c | ||
|   | 02d6ab5fe7 | ||
|   | 5547ccffd6 | ||
|   | 8c06bd1738 | ||
|   | 469a8c1017 | ||
|   | bb3602073c | ||
|   | 6c6af59b22 | ||
|   | a8a36c73e6 | ||
|   | 98b1d854f9 | ||
|   | 1ada2317fd | ||
|   | 40722c8c30 | ||
|   | ff9e255f1b | ||
|   | fbe9c31d10 | ||
|   | 0aed705a6a | ||
|   | 06e864c954 | ||
|   | 1d68d013df | ||
|   | 8e6bc73ca6 | ||
|   | 7e0fded595 | ||
|   | c8443228fb | ||
|   | 64fe0062ee | ||
|   | 3b78516ef2 | ||
|   | 8f345126f7 | ||
|   | daaa472dfe | ||
|   | 87f35da3b6 | ||
|   | 6f42a60e59 | ||
|   | 3beedc1747 | ||
|   | 6603815a81 | ||
|   | c1027d3663 | ||
|   | 6cec5ba5bf | ||
|   | d70b70b63c | ||
|   | 7d73e3cd98 | ||
|   | 5087fc4a00 | ||
|   | 30cdb1ba73 | ||
|   | 0f6612904e | ||
|   | e5b5b4d3ef | ||
|   | 9bc63bb55c | ||
|   | dcf83d5608 | ||
|   | 8fe82bb5c0 | ||
|   | 6f74029d76 | ||
|   | 01e3d366ba | ||
|   | 41d5b4a22f | ||
|   | 7814636caf | ||
|   | cf2c5e36bc | ||
|   | 5d5875d540 | ||
|   | 95c2adc02e | ||
|   | 73f1ba10f9 | ||
|   | 9fe419cfe7 | ||
|   | 41e24ca535 | ||
|   | 42a628731d | ||
|   | 2ba702df21 | ||
|   | 0171962306 | ||
|   | 2daa42e124 | ||
|   | abfd2c94f5 | ||
|   | fd51fa7779 | ||
|   | 1a36aa8904 | ||
|   | 881a28138a | ||
|   | 26fb1698b8 | ||
|   | 13d7dd98bd | ||
|   | 672a9f1712 | ||
|   | 2e560ac081 | ||
|   | 39d1127cf1 | ||
|   | 13586e664f | ||
|   | 6e6db543f7 | ||
|   | ea8ae2372e | ||
|   | 928de13459 | ||
|   | e213c3e7d8 | ||
|   | 65b4b2d183 | ||
|   | 94b145b215 | ||
|   | 6c9e6af154 | ||
|   | b5736ad559 | ||
|   | ab3912b378 | ||
|   | 3090989dea | ||
|   | 92314b8dac | ||
|   | a52396008d | ||
|   | ae7350e3a0 | ||
|   | c30300c368 | ||
|   | ed3d415c05 | ||
|   | bb353d617a | ||
|   | d7f41748ad | ||
|   | 915ae47971 | ||
|   | 40b151b4c5 | ||
|   | 1992410a7b | ||
|   | 48874f5b07 | ||
|   | 2144a4eb7c | ||
|   | cbdbf11edc | ||
|   | 515db04023 | ||
|   | d3811f1bf1 | ||
|   | 815fedf8e7 | ||
|   | 929a7b9cfa | ||
|   | f85361dbc5 | ||
|   | cb6509d09d | ||
|   | f09c129c6d | ||
|   | 602a4aa835 | ||
|   | 14d5c6311b | ||
|   | 289dd3c170 | ||
|   | 60eac97945 | ||
|   | de1d6b9629 | ||
|   | 722264a083 | ||
|   | 357d487af7 | ||
|   | 1b802b040d | ||
|   | 25afbd935c | ||
|   | e61bfd2722 | ||
|   | fe571cbef3 | ||
|   | a7c5cb8f5a | ||
|   | dedb96ef4a | ||
|   | ee49efd215 | ||
|   | 56a35eb864 | ||
|   | d478fe0c71 | ||
|   | 03467ea64e | ||
|   | 3368fbd058 | ||
|   | e84c6f7a24 | ||
|   | a0006bad73 | ||
|   | 2458393d22 | ||
|   | 787416e552 | ||
|   | 1c6b241239 | ||
|   | 7469d520c9 | ||
|   | 7e00e62427 | ||
|   | 0e39a969c3 | ||
|   | 0ad1647930 | ||
|   | d7fc45a72d | ||
|   | 54dfb642b1 | ||
|   | 40626d0f42 | ||
|   | 523afccb51 | ||
|   | 1087aefe0a | ||
|   | 9b66edc148 | ||
|   | 2c09b0ae86 | ||
|   | 8de8ad13bf | ||
|   | 70bd442bb0 | ||
|   | 5250b3189b | ||
|   | 2534651e20 | ||
|   | f46a42023f | ||
|   | e2ab301340 | ||
|   | 700f835243 | ||
|   | 9ce7162a04 | ||
|   | af85a8b711 | ||
|   | cd58008a0f | ||
|   | 1f6bd975d0 | ||
|   | b3556c008e | ||
|   | dbe83f8a74 | ||
|   | d1c50f00a0 | ||
|   | bd9d3154db | ||
|   | 1f0b4425a4 | ||
|   | 47bfea4c56 | ||
|   | 416de6b584 | ||
|   | 3d3d141b25 | ||
|   | 2ff56c17e3 | ||
|   | fb326d0354 | ||
|   | e84933cf26 | ||
|   | 8e04328482 | ||
|   | d148b71f0f | ||
|   | 4e68838172 | ||
|   | d281fc588b | ||
|   | 1799ef42a7 | ||
|   | a0d5a863e0 | ||
|   | df59b104db | ||
|   | e7e327c238 | ||
|   | ee6e68d0bf | ||
|   | d7333b3f21 | ||
|   | 375bd58a0c | ||
|   | cddd915adf | ||
|   | 9e0ad271f6 | ||
|   | a0afeb2a7a | ||
|   | 7c208b38ed | ||
|   | eaa11c68f3 | ||
|   | 92c0671da2 | ||
|   | 33d7a0436b | ||
|   | 0525295d7e | ||
|   | 87e54ac14f | ||
|   | e7fa5eb38a | ||
|   | 71b4f4a64a | ||
|   | 64de46943b | ||
|   | 90d691f251 | ||
|   | df2d83b8a0 | ||
|   | ab94d0e752 | ||
|   | b4645553f2 | ||
|   | 324ebcc997 | ||
|   | b7bb570420 | ||
|   | c991e085d4 | ||
|   | 4e935719d3 | ||
|   | 22b71ae477 | ||
|   | 305884b5ee | ||
|   | 9c143a3461 | ||
|   | d94499af86 | ||
|   | 91fd6cb4e6 | ||
|   | fcfad7cef9 | ||
|   | 7424901aca | ||
|   | 8c680608ff | ||
|   | f8ef1b3b61 | ||
|   | 2c114aa559 | ||
|   | daf8beaf26 | ||
|   | 959788cee8 | ||
|   | 7b75a61cdb | ||
|   | c071d65c67 | ||
|   | 044271ad00 | ||
|   | b8130d3fd3 | ||
|   | 4468f3dd37 | ||
|   | 0c9219f885 | ||
|   | 25ab4e187c | ||
|   | 83a51eebfb | ||
|   | 6e99c6d41f | ||
|   | ad570688c9 | ||
|   | 8378bc0d57 | ||
|   | c74bef475b | ||
|   | 3224dd9862 | ||
|   | adf47bb31c | ||
|   | 66cb0455fd | ||
|   | d56965552f | ||
|   | 07946cbeb2 | ||
|   | 33de478450 | ||
|   | bf867c522a | ||
|   | b3a4ffd4a7 | ||
|   | ff2b9c7988 | ||
|   | ad072ea83a | ||
|   | 9dae06b589 | ||
|   | 09db8e072e | ||
|   | 5ac6ff1405 | ||
|   | 9b3dbdc54f | ||
|   | e11d70de46 | ||
|   | f3ddf631c1 | ||
|   | f1c95b315c | ||
|   | 518ae4d97a | ||
|   | 2a9c28e63b | ||
|   | 900500ef28 | ||
|   | 27d76dfa42 | ||
|   | 51b848c43e | ||
|   | f005b7338f | ||
|   | 04a88c9cbd | ||
|   | 7c0c85f650 | ||
|   | ee9e939f88 | ||
|   | e5ca3daa54 | ||
|   | 8021308822 | ||
|   | d9e449b6cf | ||
|   | c94bb09123 | ||
|   | 1cd3ebf3bb | ||
|   | 2070f91a8f | ||
|   | 5b6b37a867 | ||
|   | 2dbf189f43 | ||
|   | 82e64559a8 | ||
|   | d0d77b8775 | ||
|   | 35c4988c98 | ||
|   | 10cad086f6 | ||
|   | 4d5ba90d38 | ||
|   | 3eb75708de | ||
|   | b95d333dc9 | ||
|   | 887a080198 | ||
|   | 8f3c3c6ba3 | ||
|   | f7c7552d5a | ||
|   | b61c6151eb | ||
|   | 37e2849a3a | ||
|   | a4eca93584 | ||
|   | 13d0718780 | ||
|   | 38693521b3 | ||
|   | 447ddeb6d3 | ||
|   | f11b2e9132 | ||
|   | 9d69b9d173 | ||
|   | 27a44bf9af | ||
|   | b68077d969 | ||
|   | f475c671f7 | ||
|   | 1ab32ca3ba | ||
|   | 8345b839e7 | ||
|   | 259cda150d | ||
|   | 8146c90efa | ||
|   | da3d078917 | ||
|   | 72c79e005a | ||
|   | d252138867 | ||
|   | c20183c547 | ||
|   | cd94abb7fd | ||
|   | f886245e3c | ||
|   | 4f413eec12 | ||
|   | 441bfe74c1 | ||
|   | 071289bc48 | ||
|   | 1ba2381437 | ||
|   | 1e5e576bd0 | ||
|   | 059b8824a2 | ||
|   | d7e6916d8f | ||
|   | c821f76f0f | ||
|   | e5ad1b45bd | ||
|   | 08f011eb33 | ||
|   | 1a6044090a | ||
|   | 697bf590ff | ||
|   | 4073da2431 | ||
|   | fbca43b239 | ||
|   | a03a8bf0d5 | ||
|   | 75d1ed6eea | ||
|   | dd1e604155 | ||
|   | c7f2cab56a | ||
|   | 2bd372dbaa | ||
|   | 45ecc29e12 | ||
|   | 69d068e73f | ||
|   | 0f55211dc9 | ||
|   | dbf09ef361 | ||
|   | e08557e5ae | ||
|   | aaaba5cc84 | ||
|   | 2cfd0242bd | ||
|   | 0711d555e1 | ||
|   | e8363d7310 | ||
|   | be9ce34dc8 | ||
|   | bb60d17ccc | ||
|   | 1aa8062310 | ||
|   | 711027e450 | ||
|   | 8115cc5ecc | ||
|   | 8bae67d9ef | ||
|   | bc3fd61bde | ||
|   | ba1d52d6dd | ||
|   | c02d0fc927 | ||
|   | 56738389f8 | ||
|   | d511679dbd | ||
|   | 6b931de37d | ||
|   | 56e9d85fc2 | ||
|   | 405f890dfc | ||
|   | 1145c26f2b | ||
|   | 3890222bbc | ||
|   | fba9f66a1f | ||
|   | 668387e372 | ||
|   | f85fad447e | ||
|   | 56616b805f | ||
|   | b9729ad763 | ||
|   | a26538c3f0 | ||
|   | a55ec208aa | ||
|   | 1970a00bb6 | ||
|   | 1e2267bd31 | ||
|   | 092a03e2cf | ||
|   | 065661e419 | ||
|   | 72d7dae7fa | ||
|   | 5624022064 | ||
|   | 944d532ad1 | ||
|   | 11727785c7 | ||
|   | 9b04dc0e44 | ||
|   | ca4f786aa8 | ||
|   | 152114b054 | ||
|   | 6aef5ecf4b | ||
|   | 645e7ee95f | ||
|   | 798d0948d1 | ||
|   | 008374748e | ||
|   | 3333ab4ade | ||
|   | f8c2f0f01b | ||
|   | 6dc62cca13 | ||
|   | f3e9f17b85 | ||
|   | ed14f9ada0 | ||
|   | 9250f20559 | ||
|   | 6157fdc007 | ||
|   | 5a97e53e21 | ||
|   | 901cb9eaf6 | ||
|   | 79de744936 | ||
|   | d8a70a3da6 | ||
|   | 813de7eb3c | ||
|   | 410c15c997 | ||
|   | fb9ead2690 | ||
|   | e7c381d651 | ||
|   | dca74d7b11 | ||
|   | 415b31e1b4 | ||
|   | af1a6cf5ff | ||
|   | d79ae8e927 | ||
|   | 49fe7a4b38 | ||
|   | f5374e8ce7 | ||
|   | 0c207ce12d | ||
|   | 3945c2ad52 | ||
|   | bc8f24afad | ||
|   | fd91d1fb06 | ||
|   | 6a81794bba | ||
|   | 6a89b12258 | ||
|   | 219f128cb7 | ||
|   | 89a24442c4 | ||
|   | 62eab175ab | ||
|   | e3af63bd93 | ||
|   | 78454657ca | ||
|   | 7b770e09f7 | ||
|   | 933b25194c | ||
|   | 1cbe452f9c | ||
|   | 920e9b915f | ||
|   | 99e38b1b60 | ||
|   | 2964089483 | ||
|   | 624a99b179 | ||
|   | 705277ceb5 | ||
|   | bf709786f3 | ||
|   | bda7982134 | ||
|   | abb2b36ae6 | ||
|   | 945442a842 | ||
|   | 30b231cfdf | ||
|   | cbdac66fd0 | ||
|   | 257d4dbdad | ||
|   | 69064839a7 | ||
|   | ed6a740eee | ||
|   | d594fa1a54 | ||
|   | 35e4cd4596 | ||
|   | 24319ddc7a | ||
|   | d3e3efd05e | ||
|   | 14cb37725e | ||
|   | fc3bd432ef | ||
|   | b0a5220159 | ||
|   | 9620ac7d25 | ||
|   | 7b1989cef2 | ||
|   | 601d2808a2 | ||
|   | 71b4963ed8 | ||
|   | f124c4844f | ||
|   | 7f9877b3da | ||
|   | 1526dde39d | ||
|   | 7dd6925049 | ||
|   | 6163d3fbed | ||
|   | 630d23141d | ||
|   | 0252006eb1 | ||
|   | 162777bb46 | ||
|   | 0d5b9c2f98 | ||
|   | 5f22ab0361 | ||
|   | b1fd1263f1 | ||
|   | 6226203b0e | ||
|   | 9f31f90146 | ||
|   | 5aaf15f81c | ||
|   | 5ad82a305e | ||
|   | 296e99772a | ||
|   | 1365f41b2d | ||
|   | 13199744ef | ||
|   | 4e937c32b4 | ||
|   | 559d13dfd9 | ||
|   | a94a9291e6 | ||
|   | 6ccaf316ab | ||
|   | 9fff996393 | ||
|   | 3febb340d4 | ||
|   | 5abc08ba9d | ||
|   | 2164e9a5a0 | ||
|   | c87100c0fe | ||
|   | 6a167e99dc | ||
|   | 052672402e | ||
|   | 4d566500e9 | ||
|   | 2dd51d0202 | ||
|   | 862b58c176 | ||
|   | 09b6f16a51 | ||
|   | ffebcee48b | ||
|   | 8c50a84516 | ||
|   | 7c8f87bd78 | ||
|   | ded5274be7 | ||
|   | d03989481b | ||
|   | dac59d3133 | ||
|   | 7a5333ba62 | ||
|   | f8e9fe376b | ||
|   | f9ea7af3ab | ||
|   | 622122562f | ||
|   | 3b96b21683 | ||
|   | 3fc8d01070 | ||
|   | b0603c6c7d | ||
|   | 276f3a5516 | ||
|   | 1859867039 | ||
|   | 8c83eb805b | ||
|   | 2667d2b41c | ||
|   | 1b539f82ac | ||
|   | 876b1b988a | ||
|   | e3bcbc4da9 | ||
|   | 1f9aa96486 | ||
|   | 2d17116119 | ||
|   | b592d02bb7 | ||
|   | 961d1acd51 | ||
|   | 138d22976a | ||
|   | 848507f7e8 | ||
|   | 82fed8abfe | ||
|   | 7941bdc55e | ||
|   | d1e6061541 | ||
|   | 96e55b17b1 | ||
|   | 6dab50cbd8 | ||
|   | 89f24c631c | ||
|   | 5d0a0d352b | ||
|   | 63bc0a9620 | ||
|   | 0791ccbcf5 | ||
|   | d03ab6c79f | ||
|   | 72e2a762da | ||
|   | cd0b1f10cc | ||
|   | a81824a7eb | ||
|   | 589d07ed40 | ||
|   | 9a86f1ebed | ||
|   | 2695995211 | ||
|   | ff8105f809 | ||
|   | 98a05f53d2 | ||
|   | 549b1a2f13 | ||
|   | b50d0cd710 | ||
|   | ff135c034c | ||
|   | eb93b08342 | ||
|   | 048c40c16c | ||
|   | 33b871efa6 | ||
|   | 2010094f83 | ||
|   | 693e201900 | ||
|   | 2333180c50 | ||
|   | 915e9409dc | ||
|   | b6be3226c5 | ||
|   | b83cad36b6 | ||
|   | fb1b9fea09 | ||
|   | 45a387000d | ||
|   | e6b052f8e9 | ||
|   | 6365105515 | ||
|   | 550b664a61 | ||
|   | 510459b046 | ||
|   | adbec47fad | ||
|   | ae24a4ea4c | ||
|   | db67bb0b98 | ||
|   | 857ce1324c | ||
|   | 82d6467cee | ||
|   | 887c792a76 | ||
|   | b3625dffbc | ||
|   | 90cd5dfae7 | ||
|   | 8ce791368c | ||
|   | 05e15ce9ad | ||
|   | 1926c5ec5b | ||
|   | 0bb1d869af | ||
|   | c654ea329c | ||
|   | 68d74a490b | ||
|   | 857aa110c8 | ||
|   | 6ba24eebb0 | ||
|   | 023eb3b0ff | ||
|   | bf361238cb | ||
|   | 42d23e9b37 | ||
|   | e1ddf58119 | ||
|   | 4023fda5b6 | ||
|   | f34f2da9b9 | ||
|   | 050f596429 | ||
|   | de36cfd2eb | ||
|   | b828b8e44a | ||
|   | 15da31d3eb | ||
|   | 6158d81b5e | ||
|   | b714bf4abe | ||
|   | 46ca6262b5 | ||
|   | cfef209cb7 | ||
|   | 654c038eab | ||
|   | a6beb0d2d5 | ||
|   | 515b42cd51 | ||
|   | 6668c47368 | ||
|   | b801fdc14f | ||
|   | 15dcc7b802 | ||
|   | 3ec6d5e905 | ||
|   | 92cd64c8e8 | ||
|   | 955396e575 | ||
|   | 52efadd442 | ||
|   | 09234e65fe | ||
|   | 4d0d601127 | ||
|   | bce3756e83 | ||
|   | 0cf21671a4 | ||
|   | 5d3fbb4bff | ||
|   | 68bbf4182f | ||
|   | eab416c0b4 | ||
|   | c48452b37d | ||
|   | a636a87c2b | ||
|   | ba8e1c5647 | ||
|   | fc30e28e84 | ||
|   | cfca37b09c | ||
|   | 31a3f594f1 | ||
|   | 9c536bd845 | ||
|   | 808612cd10 | ||
|   | f2c3e558cc | ||
|   | 3324154208 | ||
|   | 9c0068d470 | ||
|   | 5079027978 | ||
|   | 04dca2f274 | ||
|   | 168df5d4e2 | ||
|   | 6cf6f0460e | ||
|   | 57d8e0b06f | ||
|   | 55ab90a481 | ||
|   | 0a8fb40bd7 | ||
|   | fb026ec07f | ||
|   | 79697e9030 | ||
|   | 873e05538e | ||
|   | 9dd18a97e8 | ||
|   | 51acb739e9 | ||
|   | 7e2be69749 | ||
|   | 8e0ec47229 | ||
|   | ca4b243daa | ||
|   | 755adb0863 | ||
|   | fc6cd29e84 | ||
|   | ab73c602c3 | ||
|   | 862533fd7f | ||
|   | ffa3bed620 | ||
|   | ba8d56f6ab | ||
|   | 4bfc804d85 | ||
|   | 40981daf33 | ||
|   | 16bcb70863 | ||
|   | b1c72df333 | ||
|   | 39ced581b8 | ||
|   | 18a325cad8 | ||
|   | 7b0e891ab3 | ||
|   | fc243466da | ||
|   | 9738c1896d | ||
|   | d0976cead9 | ||
|   | 2e46d80bce | ||
|   | 283806369a | ||
|   | 500cb23ab9 | ||
|   | 88cabf88b2 | ||
|   | 9dc3d6d8d6 | ||
|   | cb8d8c4173 | ||
|   | 1949c197d6 | ||
|   | 16dab3a2cc | ||
|   | 497a073162 | ||
|   | 22e245ecff | ||
|   | b03433d8a8 | ||
|   | 4f0fca021c | ||
|   | 5aa1ae003e | ||
|   | f29758939c | ||
|   | 3703c2b431 | ||
|   | d289d9a8ff | ||
|   | a083dd048d | ||
|   | f09c30d370 | ||
|   | 9e28d46ee7 | ||
|   | c133482659 | ||
|   | bf71c1aee8 | ||
|   | 4102b44352 | ||
|   | acf2e2fb4a | ||
|   | f9de0b5eb9 | ||
|   | 85083f5979 | ||
|   | 087988dde3 | ||
|   | 2dddb853f2 | ||
|   | a92355181f | ||
|   | 2085f7e128 | ||
|   | de7366e9a9 | ||
|   | 7ab1c1170f | ||
|   | 792770e5e2 | ||
|   | dece42c155 | ||
|   | 1025fad0e6 | ||
|   | 31537687c1 | ||
|   | 9c281511fa | ||
|   | 544375378f | ||
|   | c2574235ea | ||
|   | 0533b8c946 | ||
|   | 5475bd6b5f | ||
|   | 2e4321872a | ||
|   | 515790b1a0 | ||
|   | 35c9ffcdca | ||
|   | 920c8a936f | ||
|   | 6863ba4883 | ||
|   | 2f49413867 | ||
|   | 854560b2f5 | ||
|   | 4a948b8ba2 | ||
|   | 01c0d021b2 | ||
|   | 3e49ef42a2 | ||
|   | efb1775aff | ||
|   | 2a1f1c3cd9 | ||
|   | 3c4ab10b36 | ||
|   | 1c94169182 | ||
|   | 53ab7af8dc | ||
|   | 8d173d369d | ||
|   | 4535687b48 | ||
|   | c415cf5ffb | ||
|   | a95c93cd5b | ||
|   | 62443257fc | ||
|   | 60a8317115 | ||
|   | 73ed384215 | ||
|   | c4a1f7df5f | ||
|   | 8b4eccc064 | ||
|   | 6528a4a60c | ||
|   | 4d690992ac | 
							
								
								
									
										19
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,19 @@ | |||||||
|  | # EditorConfig is awesome: https://EditorConfig.org | ||||||
|  |  | ||||||
|  | # top-most EditorConfig file | ||||||
|  | root = true | ||||||
|  |  | ||||||
|  | # with a newline ending every file | ||||||
|  | [*] | ||||||
|  | indent_style = tab | ||||||
|  | indent_size = 4 | ||||||
|  | insert_final_newline = true | ||||||
|  |  | ||||||
|  | [*.md] | ||||||
|  | trim_trailing_whitespace = false | ||||||
|  |  | ||||||
|  | [{composer.json,package.json}] | ||||||
|  | indent_style = space | ||||||
|  |  | ||||||
|  | [{package.json, *.yml}] | ||||||
|  | indent_size = 2 | ||||||
							
								
								
									
										13
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,13 @@ | |||||||
|  | * text=auto | ||||||
|  | .gitattributes export-ignore | ||||||
|  | .gitignore export-ignore | ||||||
|  | .github export-ignore | ||||||
|  | .editorconfig export-ignore | ||||||
|  | _config.yml export-ignore | ||||||
|  | release.sh export-ignore | ||||||
|  |  | ||||||
|  | # cypress | ||||||
|  | cypress export-ignore | ||||||
|  | cypress.config.js export-ignore | ||||||
|  |  | ||||||
|  | *.sh text eol=lf | ||||||
							
								
								
									
										12
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,12 @@ | |||||||
|  | # These are supported funding model platforms | ||||||
|  |  | ||||||
|  | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] | ||||||
|  | patreon: # Replace with a single Patreon username | ||||||
|  | open_collective: # Replace with a single Open Collective username | ||||||
|  | ko_fi: # Replace with a single Ko-fi username | ||||||
|  | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel | ||||||
|  | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry | ||||||
|  | liberapay: # Replace with a single Liberapay username | ||||||
|  | issuehunt: # Replace with a single IssueHunt username | ||||||
|  | otechie: # Replace with a single Otechie username | ||||||
|  | custom: paypal.me/slawkens # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] | ||||||
							
								
								
									
										29
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,29 @@ | |||||||
|  | <!-- | ||||||
|  | Please use this issue tracker only for reporting MyAAC bugs. | ||||||
|  |  | ||||||
|  | If you need support, please use the discord server: | ||||||
|  |  | ||||||
|  | - https://discord.gg/2J39Wus (we have an own channel named #my-aac there) | ||||||
|  |  | ||||||
|  | or use otland support boards: | ||||||
|  |  | ||||||
|  | - https://otland.net/forums/support.16/ | ||||||
|  |  | ||||||
|  | --> | ||||||
|  |  | ||||||
|  | ### Server configuration | ||||||
|  | - Operating System:  | ||||||
|  | - Web Server (+ version):  | ||||||
|  | - PHP Version:  | ||||||
|  | - Server name and version (for example: TFS 0.3):  | ||||||
|  | - MyAAC Version:  | ||||||
|  |  | ||||||
|  | ### Client configuration (Your Computer) | ||||||
|  |  | ||||||
|  | - Browser:  | ||||||
|  | - Operating System:  | ||||||
|  |  | ||||||
|  | ### Description: | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### Steps To Reproduce: | ||||||
							
								
								
									
										164
									
								
								.github/workflows/cypress.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,164 @@ | |||||||
|  | name: Cypress | ||||||
|  | on: | ||||||
|  |   pull_request: | ||||||
|  |     branches: [main] | ||||||
|  |   push: | ||||||
|  |     branches: [main] | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   cypress: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     services: | ||||||
|  |       mysql: | ||||||
|  |         image: mysql:8.0 | ||||||
|  |         env: | ||||||
|  |           MYSQL_ROOT_PASSWORD: root | ||||||
|  |           MYSQL_DATABASE: myaac | ||||||
|  |           MYSQL_USER: myaac | ||||||
|  |           MYSQL_PASSWORD: myaac | ||||||
|  |         ports: | ||||||
|  |           - 3306/tcp | ||||||
|  |         options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 | ||||||
|  |     strategy: | ||||||
|  |       fail-fast: false | ||||||
|  |       matrix: | ||||||
|  |         php-versions: [ '8.1', '8.2', '8.3', '8.4' ] | ||||||
|  |         ots: ['tfs-1.4', 'canary-3.1.2'] # TODO: add 'tfs-master' (actually doesn't work cause AAC doesn't support reading .env configuration) | ||||||
|  |     name: Cypress (PHP ${{ matrix.php-versions }}, ${{ matrix.ots }}) | ||||||
|  |     steps: | ||||||
|  |         - name: 📌 MySQL Start & init & show db | ||||||
|  |           run: | | ||||||
|  |             sudo /etc/init.d/mysql start | ||||||
|  |             mysql -e 'CREATE DATABASE myaac;' -uroot -proot | ||||||
|  |             mysql -e "SHOW DATABASES" -uroot -proot | ||||||
|  |  | ||||||
|  |         - name: Checkout MyAAC | ||||||
|  |           uses: actions/checkout@v4 | ||||||
|  |           with: | ||||||
|  |             ref: main | ||||||
|  |  | ||||||
|  |         - uses: actions/setup-node@v4 | ||||||
|  |           with: | ||||||
|  |             node-version: 18 | ||||||
|  |         - run: npm ci | ||||||
|  |  | ||||||
|  |         - name: Checkout TFS | ||||||
|  |           uses: actions/checkout@v4 | ||||||
|  |           if: matrix.ots == 'tfs-1.4' | ||||||
|  |           with: | ||||||
|  |             repository: otland/forgottenserver | ||||||
|  |             ref: 1.4 | ||||||
|  |             path: ots | ||||||
|  |  | ||||||
|  |         - name: Checkout TFS | ||||||
|  |           uses: actions/checkout@v4 | ||||||
|  |           if: matrix.ots == 'tfs-master' | ||||||
|  |           with: | ||||||
|  |             repository: otland/forgottenserver | ||||||
|  |             ref: master | ||||||
|  |             path: ots | ||||||
|  |  | ||||||
|  |         - name: Checkout Canary | ||||||
|  |           uses: actions/checkout@v4 | ||||||
|  |           if: matrix.ots == 'canary-3.1.2' | ||||||
|  |           with: | ||||||
|  |             repository: opentibiabr/canary | ||||||
|  |             ref: v3.1.2 | ||||||
|  |             path: ots | ||||||
|  |  | ||||||
|  |         - name: Import OTS Schema | ||||||
|  |           run: | | ||||||
|  |               mysql -uroot -proot myaac < ots/schema.sql | ||||||
|  |  | ||||||
|  |         - name: Rename config.lua | ||||||
|  |           run: mv ots/config.lua.dist ots/config.lua | ||||||
|  |  | ||||||
|  |         - name: Replace mysqlUser (TFS 1.4) | ||||||
|  |           uses: jacobtomlinson/gha-find-replace@v3 | ||||||
|  |           if: matrix.ots == 'tfs-1.4' | ||||||
|  |           with: | ||||||
|  |             find: 'mysqlUser = "forgottenserver"' | ||||||
|  |             replace: 'mysqlUser = "root"' | ||||||
|  |             regex: false | ||||||
|  |             include: 'ots/config.lua' | ||||||
|  |  | ||||||
|  |         - name: Replace mysqlPass (TFS 1.4) | ||||||
|  |           uses: jacobtomlinson/gha-find-replace@v3 | ||||||
|  |           if: matrix.ots == 'tfs-1.4' | ||||||
|  |           with: | ||||||
|  |               find: 'mysqlPass = ""' | ||||||
|  |               replace: 'mysqlPass = "root"' | ||||||
|  |               regex: false | ||||||
|  |               include: 'ots/config.lua' | ||||||
|  |  | ||||||
|  |         - name: Replace mysqlDatabase (TFS 1.4) | ||||||
|  |           uses: jacobtomlinson/gha-find-replace@v3 | ||||||
|  |           if: matrix.ots == 'tfs-1.4' | ||||||
|  |           with: | ||||||
|  |               find: 'mysqlDatabase = "forgottenserver"' | ||||||
|  |               replace: 'mysqlDatabase = "myaac"' | ||||||
|  |               regex: false | ||||||
|  |               include: 'ots/config.lua' | ||||||
|  |  | ||||||
|  |         - name: Replace mysqlDatabase (Canary) | ||||||
|  |           uses: jacobtomlinson/gha-find-replace@v3 | ||||||
|  |           if: matrix.ots == 'canary-3.1.2' | ||||||
|  |           with: | ||||||
|  |               find: 'mysqlDatabase = "otservbr-global"' | ||||||
|  |               replace: 'mysqlDatabase = "myaac"' | ||||||
|  |               regex: false | ||||||
|  |               include: 'ots/config.lua' | ||||||
|  |  | ||||||
|  |         - name: Setup PHP | ||||||
|  |           uses: shivammathur/setup-php@v2 | ||||||
|  |           with: | ||||||
|  |             php-version: ${{ matrix.php-versions }} | ||||||
|  |             extensions: mbstring, dom, fileinfo, mysql, json, xml, pdo, pdo_mysql | ||||||
|  |  | ||||||
|  |         - name: Get composer cache directory | ||||||
|  |           id: composer-cache | ||||||
|  |           run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT | ||||||
|  |  | ||||||
|  |         - name: Cache composer dependencies | ||||||
|  |           uses: actions/cache@v4 | ||||||
|  |           with: | ||||||
|  |             path: ${{ steps.composer-cache.outputs.dir }} | ||||||
|  |             # Use composer.json for key, if composer.lock is not committed. | ||||||
|  |             key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} | ||||||
|  |             #key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} | ||||||
|  |             restore-keys: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} | ||||||
|  |  | ||||||
|  |         - name: Install Composer dependencies | ||||||
|  |           run: composer install --no-progress --prefer-dist --optimize-autoloader | ||||||
|  |  | ||||||
|  |         - name: Run PHP server | ||||||
|  |           run: nohup php -S localhost:8080 > php.log 2>&1 & | ||||||
|  |  | ||||||
|  |         - name: Cypress Run | ||||||
|  |           uses: cypress-io/github-action@v6 | ||||||
|  |           env: | ||||||
|  |             CYPRESS_URL: http://localhost:8080 | ||||||
|  |             CYPRESS_SERVER_PATH: /home/runner/work/myaac/myaac/ots | ||||||
|  |  | ||||||
|  |         - name: Save screenshots | ||||||
|  |           uses: actions/upload-artifact@v4 | ||||||
|  |           if: always() | ||||||
|  |           with: | ||||||
|  |             name: cypress-screenshots-${{ matrix.php-versions }}-${{ matrix.ots }} | ||||||
|  |             path: cypress/screenshots | ||||||
|  |             if-no-files-found: ignore | ||||||
|  |  | ||||||
|  |         - name: Upload Cypress Videos | ||||||
|  |           uses: actions/upload-artifact@v4 | ||||||
|  |           if: always() | ||||||
|  |           with: | ||||||
|  |             name: cypress-videos-${{ matrix.php-versions }}-${{ matrix.ots }} | ||||||
|  |             path: cypress/videos | ||||||
|  |             if-no-files-found: ignore | ||||||
|  |  | ||||||
|  |         - name: Upload PHP Logs | ||||||
|  |           uses: actions/upload-artifact@v4 | ||||||
|  |           if: always() | ||||||
|  |           with: | ||||||
|  |             name: php-log-${{ matrix.php-versions }}-${{ matrix.ots }} | ||||||
|  |             path: php.log | ||||||
							
								
								
									
										16
									
								
								.github/workflows/phplint.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,16 @@ | |||||||
|  | name: PHP Linting | ||||||
|  | on: | ||||||
|  |   pull_request: | ||||||
|  |     branches: [main] | ||||||
|  |   push: | ||||||
|  |     branches: [main] | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   phplint: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/checkout@v3 | ||||||
|  |       - uses: overtrue/phplint@8.2 | ||||||
|  |         with: | ||||||
|  |           path: . | ||||||
|  |           options: --exclude=*.log | ||||||
							
								
								
									
										46
									
								
								.github/workflows/phpstan.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,46 @@ | |||||||
|  | name: "PHPStan" | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   pull_request: | ||||||
|  |     branches: [main] | ||||||
|  |   push: | ||||||
|  |     branches: [main] | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   tests: | ||||||
|  |     name: PhpStan on PHP ${{ matrix.php-versions }} | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |  | ||||||
|  |     strategy: | ||||||
|  |       fail-fast: false | ||||||
|  |       matrix: | ||||||
|  |         php-versions: [ '8.1', '8.2', '8.3', '8.4' ] | ||||||
|  |     steps: | ||||||
|  |       - name: "Checkout" | ||||||
|  |         uses: "actions/checkout@v4" | ||||||
|  |  | ||||||
|  |       - name: "Install PHP" | ||||||
|  |         uses: "shivammathur/setup-php@v2" | ||||||
|  |         with: | ||||||
|  |           coverage: "none" | ||||||
|  |           extensions: "intl, zip" | ||||||
|  |           ini-values: "memory_limit=-1" | ||||||
|  |           php-version: "${{ matrix.php-version }}" | ||||||
|  |  | ||||||
|  |       - name: Get composer cache directory | ||||||
|  |         id: composer-cache | ||||||
|  |         run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT | ||||||
|  |  | ||||||
|  |       - name: Cache composer dependencies | ||||||
|  |         uses: actions/cache@v4 | ||||||
|  |         with: | ||||||
|  |           path: ${{ steps.composer-cache.outputs.dir }} | ||||||
|  |           # Use composer.json for key, if composer.lock is not committed. | ||||||
|  |           key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} | ||||||
|  |           restore-keys: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} | ||||||
|  |  | ||||||
|  |       - name: "Install composer dependencies" | ||||||
|  |         run: "composer install" | ||||||
|  |  | ||||||
|  |       - name: "Run PHPStan" | ||||||
|  |         run: "/usr/bin/php vendor/bin/phpstan analyse" | ||||||
							
								
								
									
										78
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,78 @@ | |||||||
|  | Thumbs.db | ||||||
|  | .DS_Store | ||||||
|  | .idea | ||||||
|  |  | ||||||
|  | # | ||||||
|  | /.htaccess | ||||||
|  | lua | ||||||
|  |  | ||||||
|  | # composer | ||||||
|  | composer.phar | ||||||
|  | vendor | ||||||
|  |  | ||||||
|  | # npm | ||||||
|  | node_modules | ||||||
|  | tools/ext | ||||||
|  |  | ||||||
|  | # cypress | ||||||
|  | cypress.env.json | ||||||
|  | cypress/e2e/2-advanced-examples | ||||||
|  | cypress/screenshots | ||||||
|  |  | ||||||
|  | # created by release.sh | ||||||
|  | releases | ||||||
|  | tmp | ||||||
|  |  | ||||||
|  | config.local.php | ||||||
|  |  | ||||||
|  | # all custom templates | ||||||
|  | templates/* | ||||||
|  | !templates/tibiacom | ||||||
|  | !templates/kathrine | ||||||
|  |  | ||||||
|  | # guild images | ||||||
|  | images/guilds/* | ||||||
|  | !images/guilds/default.gif | ||||||
|  |  | ||||||
|  | # editor images | ||||||
|  | images/editor/* | ||||||
|  | !images/editor/index.html | ||||||
|  |  | ||||||
|  | # gallery images | ||||||
|  | images/gallery/* | ||||||
|  | !images/gallery/index.html | ||||||
|  | !images/gallery/demon.jpg | ||||||
|  | !images/gallery/demon_thumb.gif | ||||||
|  |  | ||||||
|  | # cache | ||||||
|  | system/cache/* | ||||||
|  | !system/cache/index.html | ||||||
|  | !system/cache/twig/index.html | ||||||
|  | !system/cache/signatures/index.html | ||||||
|  | !system/cache/plugins/index.html | ||||||
|  | !system/cache/persistent/index.html | ||||||
|  |  | ||||||
|  | # logs | ||||||
|  | system/logs/* | ||||||
|  | !system/logs/index.html | ||||||
|  |  | ||||||
|  | # data | ||||||
|  | system/data/* | ||||||
|  | !system/data/index.html | ||||||
|  |  | ||||||
|  | # php sessions | ||||||
|  | system/php_sessions/* | ||||||
|  | !system/php_sessions/index.html | ||||||
|  |  | ||||||
|  | # plugins | ||||||
|  | plugins/* | ||||||
|  | !plugins/.htaccess | ||||||
|  | !plugins/example.json | ||||||
|  | !plugins/account-create-hint.json | ||||||
|  | !plugins/account-create-hint | ||||||
|  | !plugins/email-confirmed-reward.json | ||||||
|  | !plugins/email-confirmed-reward | ||||||
|  | landing | ||||||
|  |  | ||||||
|  | # system | ||||||
|  | system/functions_custom.php | ||||||
| @@ -1,7 +1,21 @@ | |||||||
| Options -Indexes -MultiViews | <IfModule mod_autoindex.c> | ||||||
|  | 	Options -Indexes | ||||||
|  | </IfModule> | ||||||
|  |  | ||||||
| RewriteEngine On | <IfModule mod_negotiation.c> | ||||||
|  | 	Options -MultiViews | ||||||
|  | </IfModule> | ||||||
|  |  | ||||||
| RewriteCond %{REQUEST_FILENAME} !-f | <FilesMatch "^(.*\.md|.*\.json|.*\.dist|.*\.sql|CHANGELOG|README|composer\.lock)$"> | ||||||
| RewriteCond %{REQUEST_FILENAME} !-d | 	Require all denied | ||||||
| RewriteRule ^.*$ index.php [L] | </FilesMatch> | ||||||
|  |  | ||||||
|  | <IfModule mod_rewrite.c> | ||||||
|  | 	RewriteEngine On | ||||||
|  |  | ||||||
|  | 	#RewriteBase /myaac/ | ||||||
|  |  | ||||||
|  | 	RewriteCond %{REQUEST_FILENAME} !-f | ||||||
|  | 	RewriteCond %{REQUEST_FILENAME} !-d | ||||||
|  | 	RewriteRule ^.*$ index.php [L] | ||||||
|  | </IfModule> | ||||||
|   | |||||||
							
								
								
									
										377
									
								
								CHANGELOG
									
									
									
									
									
								
							
							
						
						| @@ -1,377 +0,0 @@ | |||||||
| [0.7.4 - 24.12.2017] |  | ||||||
| 	* fixed mysql fatal error on tibiacom template - top 5 box |  | ||||||
| 	* fixed displaying of level percent bar on tibian signature |  | ||||||
| 	* inform user about Twig cache failure on installation, instead of http 500 error |  | ||||||
| 	* when dir system/cache is not writable by the webserver, then show some nice notice to the user about it instead of http 500 error |  | ||||||
| 	* remember client version select and usage stats checkbox in session on install |  | ||||||
| 	* automatically update highscores_ids_hidden for users who installed myaac before (migration) |  | ||||||
|  |  | ||||||
| [0.7.3 - 18.12.2017] |  | ||||||
| 	* auto generate myaac cache & session prefix on install to be unique across installations |  | ||||||
| 	* fixed hiding shop system menu on tibiacom template when disabled in config |  | ||||||
| 	* prevent adding duplicated newses with installation |  | ||||||
| 	* some changes to sample characters: chanced town_id to 1, posx: 1000, posy: 1000, posz: 1000 and default group_id to 1 so you can change in-game outfits and they will be used |  | ||||||
| 	* added version 772 constant to install client choose (OTHire) |  | ||||||
| 	* better solution for hidding samples (configurable) - highscores_ids_hidden |  | ||||||
| 	* fixed account.login redirect not working on tibiacom template |  | ||||||
| 	* installation: warn about wrong admin account name/id and password |  | ||||||
| 	* fixed last menu closing in tibiacom template |  | ||||||
| 	* updated polish locale (translation) on install  |  | ||||||
| 	* (internal) removed some duplicated code on install finish |  | ||||||
| 	* (internal) renamed installation step files to be in correct order |  | ||||||
| 	* added TODO file |  | ||||||
|  |  | ||||||
| [0.7.1 - 13.12.2017] |  | ||||||
| 	* added changelog menu item to kathrine template |  | ||||||
| 	* fixed some php short tag in changelogs page |  | ||||||
| 	* fixed guild change description back button |  | ||||||
| 	* removed duplicated "Support List" menu item from tibiacom template |  | ||||||
| 	* changed some notice when version check is failed |  | ||||||
| 	* (internal) moved changelog to twig |  | ||||||
|  |  | ||||||
| [0.7.0 - 20.11.2017] |  | ||||||
| 	* moved template menus to database, they're now dynamically loaded |  | ||||||
| 	* added anonymous usage statistics reporting (only if user agrees, first usage report will be send after 7 days) |  | ||||||
| 	* you can edit them in Admin Panel under 'Menus' option |  | ||||||
| 	* you can also add custom links, like http://google.pl |  | ||||||
| 	* added networks (facebook and twitter) and highscores (top 5) boxes to tibiacom template, configurable in templates/tibiacom/config.php |  | ||||||
| 	* added news ticker for kathrine template |  | ||||||
| 	* added featured article to tibiacom template (you can add them with add news button) |  | ||||||
| 	* added tinymce editor to 'Pages' in admin panel |  | ||||||
| 	* added links to edit/delete/hide custom page directly from page |  | ||||||
| 	* update forum post after editing news (when forum post has been created) |  | ||||||
| 	* enabled code plugin for tinymce which enabled raw html code editing |  | ||||||
| 	* removed videos pages, as it can be easily added using custom Menus and Pages with insert Media |  | ||||||
| 	* removed bug_report configurable, its now enabled by default |  | ||||||
| 	* log some error info when mail cannot be send on account create |  | ||||||
| 	* twig getLink function will now return with full url (BASE_URL included) |  | ||||||
| 	* verify install post values directly on config page and display error |  | ||||||
| 	* updated tinymce to version 4.7.2 (from 4.7.0) |  | ||||||
| 	* updated phpmailer to version 5.2.26 (from 5.2.23) |  | ||||||
| 	* (#30) (fix) recovering account on servers that doesn't support salts |  | ||||||
| 	* (fix) account email confirm function |  | ||||||
| 	* (fix) showing changelog with urls in Admin Panel |  | ||||||
| 	* (fix) uninstalling plugin |  | ||||||
| 	* (fix) polls box in tibiacom template |  | ||||||
| 	* (fix) remove hooks from db on plugin deinstall |  | ||||||
| 	* (fix) some weird include possibilities with forum and account actions (verify action name) |  | ||||||
| 	* (fix) loading hooks from plugin installed from command line |  | ||||||
| 	* (fix) some changelog PHP Notice warning |  | ||||||
| 	* (internal) moved uninstall logic to Plugins class |  | ||||||
| 	* (internal) moved tibiacom boxes to separate directory |  | ||||||
| 	* (internal) moved news tickers to twig template |  | ||||||
| 	* (internal) moved Forum class to separate file |  | ||||||
| 	* (internal) moved deprecated functions to compat.php |  | ||||||
| 	* (internal) added some compat functions that are used by shop system |  | ||||||
| 	* (internal) renamed constant TICKET -> TICKER |  | ||||||
| 	* (internal) shortened message functions |  | ||||||
| 	 |  | ||||||
| [0.6.6 - 22.10.2017] |  | ||||||
| 	* fixed some php fatal error on spells page |  | ||||||
| 	* changed spells.vocations field in db size to 300 |  | ||||||
| 	* please reload your spells after this update! |  | ||||||
|  |  | ||||||
| [0.6.5 - 21.10.2017] |  | ||||||
| 	* fixed displaying custom pages |  | ||||||
| 	* fixed adding new group forum board |  | ||||||
| 	 |  | ||||||
| [0.6.4 - 20.10.2017] |  | ||||||
| 	* reverted OTS_Account::getLastLogin() cause its used by tibia11-login plugin |  | ||||||
| 	 |  | ||||||
| [0.6.3 - 20.10.2017] |  | ||||||
| 	* fixed creating account |  | ||||||
| 	* fixed viewing thread without being logged  |  | ||||||
| 	* fixed showing premium account status |  | ||||||
| 	 |  | ||||||
| [0.6.2 - 20.10.2017] |  | ||||||
| 	* added forums for guilds and groups |  | ||||||
| 	* added nice looking menu for my account page in default template |  | ||||||
| 	* new command line tool: install_plugin.php - can be used to install plugins from command line. Usage: "php install_plugin.php path_to_file" |  | ||||||
| 	* added new tooltip to view characters equipment item name and monster loot |  | ||||||
| 	* added items.xml loader class and weapons.xml loader class |  | ||||||
| 	* minimum PHP version to install AAC is now 5.3.0 cause of Anonymous functions used by Twig |  | ||||||
| 	* Added 'Are you sure?' popup when uninstalling plugin |  | ||||||
| 	* added some warnings when plugin json file is incomplete |  | ||||||
| 	* fixed showing in characters ban expires when is unlimited |  | ||||||
| 	* fixed displaying monster loot when item.name in loot is used instead of item.id |  | ||||||
| 	* load also runes into spells table |  | ||||||
| 	* display plugin uninstall option only if its possible |  | ||||||
| 	* after changing template you will be redirected to latest viewed page |  | ||||||
| 	* display gallery add image form only on main gallery page |  | ||||||
| 	* (internal) moved most of guilds html-in-php code to twig |  | ||||||
| 	* (internal) moved spells page to twig template |  | ||||||
| 	* (internal) removed useless spells.spell column that was duplicate of spells.words |  | ||||||
| 	* (internal) save monster loot in database in json format instead loading it every time from xml file |  | ||||||
| 	* (internal) store monster voices and immunities in json format |  | ||||||
| 	* (internal) moved buttons to separate template |  | ||||||
| 	* (internal) moved online search form to twig |  | ||||||
| 	* (internal) added new function getItemNameById($id) |  | ||||||
| 	* (internal) Moved plugin install logic to a new class: Plugins |  | ||||||
| 	* (internal) changed spells.vocations database field to store json data instead of comma separated |  | ||||||
| 	* (internal) removed $hook_types array, using defined() and constant() functions now |  | ||||||
| 	* (internal) removed useless monsters.gfx_name field from database |  | ||||||
| 	* (internal) renamed database field monsters.hide_creature to hidden |  | ||||||
| 	* (internal) renamed existing Items class to Items_Images |  | ||||||
| 	* (internal) optimized Spells class |  | ||||||
| 	* (internal) new function: OTS_Guild::hasMember(OTS_Player $player) |  | ||||||
| 	* (internal) new function: Forum::hasAccess($board_id) |  | ||||||
| 	 |  | ||||||
| [0.6.1 - 17.10.2017] |  | ||||||
| 	* fixed signatures loading |  | ||||||
| 	* new configurable: session_prefix, to allow more websites on one machine (must be unique for every website on your dedicated server!) |  | ||||||
| 	* better error handling for monsters and spells loader (save errors to system/logs/error.log) |  | ||||||
| 	* check if file exist before loading (monsters and spells) |  | ||||||
| 	* (internal) Account::getAccess() = Account::getGroupId() |  | ||||||
| 	* (internal) moved account actions (pages) to account/ directory |  | ||||||
| 	* (internal) moved forum actions (pages) to forum/ directory |  | ||||||
| 	* (internal) moved forum.edit_post to twig templates |  | ||||||
|  |  | ||||||
| [0.6.0 - 16.10.2017] |  | ||||||
| 	* added faq management - add/edit/move/hide/delete from website |  | ||||||
| 	* new account.login view for tibiacom template |  | ||||||
| 	* monsters and spells are now being loaded at the installation of the AAC |  | ||||||
| 	* fix for php versions under 5.5 where empty() function supported only variables |  | ||||||
| 	* added missing change email and change info buttons to account.management default template |  | ||||||
| 	* added new indicator icons for create account, create character and change character name |  | ||||||
| 	* fixed config loader when some inline comments are present |  | ||||||
| 	* fixed editing page in admin panel that contains some html code |  | ||||||
| 	* fixed forum new post on mac os and some specific mysql versions |  | ||||||
| 	* attempt to fix incorrect views counter behavior (its resetting to 0 in some cases) |  | ||||||
| 	* enabled cache http headers for signatures |  | ||||||
| 	* check if monster file exist before loading it |  | ||||||
| 	* fixed if plugin zip file name contains dot (.) |  | ||||||
| 	* renamed screenshots to gallery and movies to videos |  | ||||||
| 	* moved install pages to twig |  | ||||||
| 	* fixed Account::getGuildAccess function |  | ||||||
| 	* removed never used library from sources - dwoo |  | ||||||
| 	* moved check_* functions to class Validator |  | ||||||
| 	* from now all validators ajax requests will fire onblur instead of onkeyup |  | ||||||
| 	* ajax requests returns now json instead of xml |  | ||||||
| 	* added 404 response when file is not found |  | ||||||
|  |  | ||||||
| [0.5.1 - 11.10.2017] |  | ||||||
| 	* fixed forum add/edit board |  | ||||||
| 	* new configurable: highscores_length, how much highscores to display |  | ||||||
| 	* fixed highscores links (ALL, previous and next page) |  | ||||||
| 	* update templates cache when installing/uninstalling plugin |  | ||||||
| 	* moved character deaths and frags table generation to twig |  | ||||||
| 	* fixed some bug when you uninstall plugin and then try to install again on the same page |  | ||||||
| 	* check if plugin exist before uninstalling |  | ||||||
| 	* fixed some warning in OTS_Base_DB |  | ||||||
|  |  | ||||||
| [0.5.0 - 10.10.2017] |  | ||||||
| 	* moved .htaccess rules to plain php (index.php) |  | ||||||
| 	* updated tinymce to the latest (4.7.0) version, you can now embed code, for example youtube videos |  | ||||||
| 	* added option to uninstall plugin |  | ||||||
| 	* added option to require specified myaac, php or database version for plugins, without that plugin won't be installed |  | ||||||
| 	* change accountmanagement links to use friendly_urls |  | ||||||
| 	* fixed creating new forum thread |  | ||||||
| 	* sample characters are now assigned to admin account and have group_id 4 to not be shown on highscores |  | ||||||
| 	* added links loaded from database to admin panel - for future plugins |  | ||||||
| 	* print some info to error.log when can't find config.lua |  | ||||||
| 	* some fixes in account changecomment action |  | ||||||
| 	* show info when account name/number or password is empty on login |  | ||||||
| 	* fixed showing account login errors |  | ||||||
| 	* added few characters hooks |  | ||||||
| 	* fixed some kathrine template js bug when shop is disabled |  | ||||||
| 	* you can now use slash '/' in custom pages loaded from database |  | ||||||
| 	* added new twig function getLink that convert link taking into account config.friendly_urls |  | ||||||
| 	* internalLayoutLink -> getLink |  | ||||||
|  |  | ||||||
| [0.4.3 - 05.10.2017] |  | ||||||
| 	* better config loader taken from latest gesior, you can now include files in your config by doing dofile('config.local.lua') |  | ||||||
| 	* fixed country detection in create account |  | ||||||
| 	* fixed showing of character deaths and frags |  | ||||||
| 	* fixed https://otland.net/threads/myaac-v0-0-1.251454/page-13#post-2466303 |  | ||||||
| 	* fixed https://otland.net/threads/myaac-v0-0-1.251454/page-13#post-2466313 |  | ||||||
| 	* fixed rook sample, which will now have level 1, 150 health, 0 mana, and 400 cap. |  | ||||||
| 	* fixed samples being deleted by tfs 1.0+ cause of 'deletion' field set to 1 |  | ||||||
| 	* pages loaded from database have higher priority than normal .php pages, so they will be loaded first if they exist |  | ||||||
| 	* moved many pages to twig templates |  | ||||||
| 	* change download client links from clients.halfaway.net to tibia-clients.com |  | ||||||
| 	* added bugtracker to kathrine template |  | ||||||
| 	* added CREDITS file |  | ||||||
|  |  | ||||||
| [0.4.2 - 14.09.2017] |  | ||||||
| 	* updated version number |  | ||||||
|  |  | ||||||
| [0.4.1 - 13.09.2017] |  | ||||||
| 	* fixed log in to admin panel |  | ||||||
| 	* fixed File is not .zip plugin upload error |  | ||||||
|  |  | ||||||
| [0.4.0 - 13.09.2017 |  | ||||||
| 	* added option to add/edit/delete/hide/move forum boards |  | ||||||
| 	* moved some of HTML-in-PHP code to Twig templates |  | ||||||
| 	* added bug_report configurable which can enable/disable bug tracker |  | ||||||
| 	* log errors instead of showing them to users with system directories |  | ||||||
| 	* fix when $_SERVER['HTTP_ACCEPT_ENCODING'] is not set |  | ||||||
| 	* when it fails to load config.lua it will output error also to error.log |  | ||||||
| 	* automatically detect json file in .zip instead of basing on filename (admin panel - plugins) |  | ||||||
| 	* hopefully fixed the error with "The file you are trying to upload is not a .zip file. Please try again." |  | ||||||
| 	* fixed wrong name of table in bugtracker |  | ||||||
| 	* fixed some bugs in bugtracker |  | ||||||
| 	* added report bug link in templates |  | ||||||
| 	* fixed some rare error when user is logged in for longer than 15 minutes and tries to login again |  | ||||||
| 	* fixed some grammar errors |  | ||||||
| 	* some small improvements |  | ||||||
| 	* fixed some separators in kathrine template |  | ||||||
|  |  | ||||||
| [0.3.0 - 28.08.2017] |  | ||||||
| 	* added administration panel for screenshots management with auto thumbnail generator and image auto-resizing |  | ||||||
| 	* added Twig template engine and moved some html-in-php code to it |  | ||||||
| 	* automatically detect player country based on user location (IP) on create account |  | ||||||
| 	* player sex (gender) is now configurable at $config['genders'] |  | ||||||
| 	* fixed recovering account and changing password when salt is enabled |  | ||||||
| 	* fixed installing samples when for example Rook Sample already exist and other samples not |  | ||||||
| 	* fixed some mysql error when character you trying to create already exist |  | ||||||
| 	* fixed some warning when you select nonexistent country |  | ||||||
| 	* password change minimal/maximal length notice is now more precise |  | ||||||
| 	* added 'enabled' field in myaac_hooks table, which can enable or disable specified hook |  | ||||||
| 	* removed DEFAULT '' for TEXT field. It didn't worked under some systems like MAC OS X. |  | ||||||
| 	* minimum PHP version to install the MyAAC is now 5.2.0 cause of pathinfo (extension) function |  | ||||||
| 	* removed unused admin stylish template |  | ||||||
| 	* removed some unused cities field from myaac_spells table |  | ||||||
| 	* moved news adding at installation from schema.sql to finish.php |  | ||||||
| 	* some optimizations |  | ||||||
|  |  | ||||||
| [0.2.4 - 09.06.2017] |  | ||||||
| 	* fixed invite to guild |  | ||||||
| 	* added id field on monsters, so you can delete them in phpmyadmin |  | ||||||
| 	* fixed adding some creatures with ' and " |  | ||||||
| 	* fixed when there are spaces at beginning of the file (creatures) |  | ||||||
| 	* fixed when file is unable to parse (creatures) |  | ||||||
| 	* fixed typo loss_items => loss_containers |  | ||||||
| 	* more elegant way of showing message on reload creatures and spells |  | ||||||
|  |  | ||||||
| [0.2.3 - 31.05.2017] |  | ||||||
| 	* fixed guild management on OTHire 0.0.3 |  | ||||||
| 	* set default skills to 10 when creating new character |  | ||||||
| 	* fixed displaying of "Create forum thread" in newses |  | ||||||
| 	* fixed deleting guild on servers that use players.rank_id field |  | ||||||
| 	* fixed phpmailer class loading (https://otland.net/threads/myaac-v0-0-1.251454/page-8#post-2445222) |  | ||||||
| 	* fixed displaying vocation amount on online page |  | ||||||
| 	* better support for custom vocations, you just need to set in config vocations_amount to yours. |  | ||||||
| 	* fixed huge space in player name (https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2444328) |  | ||||||
| 	* fixed Undefined variable (https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2444034) |  | ||||||
| 	* fixed Undefined offset (https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2444035) |  | ||||||
|  |  | ||||||
| [0.2.2 - 22.05.2017] |  | ||||||
| 	* added missing cache/signature directory |  | ||||||
| 	* fixed https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2443868 |  | ||||||
|  |  | ||||||
| [0.2.1 - 21.05.2017] |  | ||||||
| 	* added Swedish translation by Sizaro |  | ||||||
| 	* fixed some bugs with installlation & characters & houses |  | ||||||
|  |  | ||||||
| [0.2.0 - 21.05.2017] |  | ||||||
| 	* added option to change character sex for premium points |  | ||||||
| 	* moved site_closed to database, now you can close your site through admin panel |  | ||||||
| 	* added option to admin panel: clear cache |  | ||||||
| 	* added experiencetable_rows configurable |  | ||||||
| 	* optimized OTS_Account->getGroupId(), now its using like 20 queries less |  | ||||||
| 	* optimized OTS_Player->load($id) function, should be much faster now |  | ||||||
| 	* fixed displaying on highscores special outfits |  | ||||||
| 	* fixed skull images displaying |  | ||||||
| 	* fixed displaying unlimited premium account |  | ||||||
| 	* fixed bug where players.lookaddons doesn't exist (OTHire etc.) (https://otland.net/threads/myaac-v0-0-1.251454/page-6#post-2442407) |  | ||||||
| 	* fixed signature tibian for OTHire and other servers that doesnt use accounts.premdays field |  | ||||||
| 	* fixed when player name in signature containst space |  | ||||||
| 	* don't show "Create forum thread" when editing |  | ||||||
| 	* fixed red color table after create account |  | ||||||
| 	* updated download links, as clients.halfaway.net isn't working anymore |  | ||||||
| 	* fixed some bugs while installing when field `email_next` or `hidden` already exist |  | ||||||
| 	* fixed movies unexpected comment |  | ||||||
| 	* added template_place_holder('center_top') to kathrine template |  | ||||||
|  |  | ||||||
| [0.1.5 - 13.05.2017] |  | ||||||
| 	* fixed bug with "Integrity constraint violation: 1048 Column 'ip' cannot be null" |  | ||||||
|  |  | ||||||
| [0.1.4 - 13.05.2017] |  | ||||||
| 	* added outfit shower, in characters, online, and highscores |  | ||||||
| 	* updated database to version 2 |  | ||||||
| 	* fixed item images (now using item-images.ots.me host by default) |  | ||||||
| 	* fixed news ticket and posting long newses (https://otland.net/threads/myaac-v0-0-1.251454/page-5#post-2442026) |  | ||||||
| 	* news body limit increased to 65535 (mysql text field) |  | ||||||
| 	* removed some unused code from my old server |  | ||||||
| 	* added spells & monsters to kathrine template |  | ||||||
|  |  | ||||||
| [0.1.3 - 11.05.2017] |  | ||||||
| 	* this is just release to update version number |  | ||||||
|  |  | ||||||
| [0.1.2 - 11.05.2017] |  | ||||||
| 	* forgot to update CHANGELOG and MYAAC_VERSION |  | ||||||
|  |  | ||||||
| [0.1.1 - 11.05.2017] |  | ||||||
| 	* fixed updating myaac_config with database_version to 1 |  | ||||||
| 	* fixed database updater |  | ||||||
|  |  | ||||||
| [0.1.0 - 11.05.2017] |  | ||||||
| 	* added new feature: change character name for premium points (disabled by default, you can enable it in config under account_change_character_name in config.php) |  | ||||||
| 	* added automatic database updater (data migrations) |  | ||||||
| 	* renamed events to hooks |  | ||||||
| 	* moved hooks to database |  | ||||||
| 	* now you can use hooks in plugins |  | ||||||
| 	* set account.type field to 5 on install, if TFS 1.0+ |  | ||||||
| 	* added example plugin |  | ||||||
| 	* new, latest google analytics code |  | ||||||
| 	* fixed bug with loading account.name that has numbers in it |  | ||||||
| 	* fixed many bugs in player editor in admin panel |  | ||||||
| 	* added error handling to plugin manager and some more verification in |  | ||||||
| 	* file has been correctly unpacked/uploaded |  | ||||||
| 	* fixed Statistics page in admin panel when using account.number |  | ||||||
| 	* fixed bug when creating/recovering account on servers with |  | ||||||
| 	* account.salt field (TFS 0.3 for example) |  | ||||||
| 	* fixed forum showing thread with html tags (added from news manager) |  | ||||||
| 	* new, latest code for youtube videos in movies page |  | ||||||
| 	* fixed showing vocation images when using $config['online_vocations_images'] |  | ||||||
| 	* many fixes in polls (also importing proper schema) |  | ||||||
| 	* fixed hovering on buttons in kathrine template (on accountmanagement page) |  | ||||||
| 	* fixed signatures (many fixes) |  | ||||||
| 	* added missing gesior signature system |  | ||||||
|  |  | ||||||
| [0.0.6 - 06.05.2017] |  | ||||||
| 	* fixed bug while installing (https://otland.net/threads/myaac-v0-0-1.251454/page-3#post-2440543) |  | ||||||
| 	* fixed bug when creating character (not showing errors) (one more time) |  | ||||||
| 	* fixed support for TFS 0.2 series |  | ||||||
| 	* added FAQ link |  | ||||||
| 	 |  | ||||||
| [0.0.5 - 05.05.2017] |  | ||||||
| 	* fixed bug when creating character (not showing errors) |  | ||||||
| 	* Fixed characters loading with names that has been created with other AAC |  | ||||||
| 	* fixed links to shop in default template |  | ||||||
| 	* fixed some weird PHP 7.1 warnings/notices |  | ||||||
| 	* Fixed config loading with some weird comments |  | ||||||
| 	* fixed bug with status info utf8 encoding (https://otland.net/threads/myaac-v0-0-1.251454/page-2#post-2440259) |  | ||||||
| 	* fixed when ip in log_action is NULL (https://otland.net/threads/myaac-v0-0-1.251454/page-2#post-2440357) |  | ||||||
| 	* fixed bug when guild doesn't exist on characters page (https://otland.net/threads/myaac-v0-0-1.251454/page-2#post-2440320) |  | ||||||
| 	* disabled friendly_urls by default |  | ||||||
| 	* fixes when $config['database_*'] is set |  | ||||||
| 	* added CHANGELOG |  | ||||||
|  |  | ||||||
| [0.0.3 - 03.05.2017] |  | ||||||
| 	* Full support for OTHire 0.0.3 |  | ||||||
| 	* added support for otservers that doesn't use account.name field, instead just account number will be used |  | ||||||
| 	* fixed encryption detection on TFS 0.3 |  | ||||||
| 	* fixed bug when server_config table doesn't exist |  | ||||||
| 	* (install) moved admin account creation to new step |  | ||||||
| 	* fixed news comment link |  | ||||||
| 	* by default, the installer creates now the Admin player, for admin account |  | ||||||
| 	* fixed installation errors |  | ||||||
| 	* fixed config.lua loading with some weird comments |  | ||||||
|  |  | ||||||
| [0.0.2 - 02.05.2017] |  | ||||||
| 	* updated forum links to use friendly_urls |  | ||||||
| 	* some more info will be shown when cannot connect to database |  | ||||||
| 	* show more error infos when creating character |  | ||||||
| 	* fixed forum link on newses |  | ||||||
| 	* fixed spells loading when there's vocation name instead of id |  | ||||||
| 	* fixed bug when you have changed template but it doesn't exist anymore |  | ||||||
| 	* fixed vocations with promotion loading |  | ||||||
| 	* fixed support for gesior pages and templates |  | ||||||
| 	* added function OTS_Acount:getGroupId() |  | ||||||
|  |  | ||||||
| [0.0.1 - 01.05.2017] |  | ||||||
| 	This is first official release of MyAAC. |  | ||||||
| 	Features are listed here |  | ||||||
|  |  | ||||||
| 	For more information, see the release announcement on OTLand: https://otland.net/threads/myaac-v0-0-1.251454/ |  | ||||||
							
								
								
									
										446
									
								
								CHANGELOG-1.x.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,446 @@ | |||||||
|  | # Changelog | ||||||
|  |  | ||||||
|  | ## [1.8.3 - 21.10.2025] | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * Feature: resend email verify (https://github.com/slawkens/myaac/commit/fe821c58085483e70491dcf76376ad5b96de3fdd) | ||||||
|  | * New config: hooks_debug (To view where hooks are located in .twig files) (https://github.com/slawkens/myaac/commit/8c3cb0e06f9709c1de3398b48221241e7cbdd310) | ||||||
|  | * Functions: Add db->getColumnInfo(table, column) (https://github.com/slawkens/myaac/commit/c898fe25efff6793a01d11c26fc153cb23fcb858) | ||||||
|  | * Plugins: Add option to use ?subtopic=x for plugins pages (https://github.com/slawkens/myaac/commit/97f9d3d6f6c28aef6d824973058d7133f56e09c4) | ||||||
|  | * getTopPlayers() Function - Add lookmount & promotion (https://github.com/slawkens/myaac/commit/2da0024c68f1cedc38a16ebbc6f52ffa55e65f7a, https://github.com/slawkens/myaac/commit/901df48d134079d648a18f9d82b60182e818ac02) | ||||||
|  | * New hooks for account/change-password (https://github.com/slawkens/myaac/commit/470555f2687809a0c12491bbb27597e64b8929c1) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Feature: show vip days in account management (https://github.com/slawkens/myaac/commit/c88b08eb1ec1f560cbfdaaa16b24e3a0f26da7b3, by @andreoam) | ||||||
|  | * Allow links in error_box.html.twig (https://github.com/slawkens/myaac/commit/9acad15451071639acf7a7d4e81619b0a9742b12) | ||||||
|  | * Canary - Comment code to update lastday in login.php (https://github.com/slawkens/myaac/commit/38902c30d114fdbce259467f5820f97037b393e9) | ||||||
|  | * Cache::remember $ttl = -1 = infinite (https://github.com/slawkens/myaac/commit/64acf70d3854182d88aaf0b67f77cea2a254f179) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Online - Allow for html code (example - img) in online_datacenter (https://github.com/slawkens/myaac/commit/3bb272ebbbd2eb7769d174b7082061d14a17bd44) | ||||||
|  | * Guilds - Fix guild create with freePremium enabled (https://github.com/slawkens/myaac/commit/c91bb5d4097647dca2196d3dea87bc90c89181d2) | ||||||
|  | * Canary - Fix premDays count (https://github.com/slawkens/myaac/commit/3e61692780d4add93b7b0e9f12f7a283bd8f4b7a) | ||||||
|  | * Template Change: Ignore set last visit for AJAX pages - Fixes template change redirect (https://github.com/slawkens/myaac/commit/89fae38caa7e4f645957fcf1a9330a36358ac04f) | ||||||
|  | * Admin Panel - Accounts: Fix lastip v6 (TFS master) (https://github.com/slawkens/myaac/commit/f54b1bdd2af4c16c64ddff0e87a6c96bc4cf9eeb) | ||||||
|  | * Functions - Prevent injection in $db->hasColumn (https://github.com/slawkens/myaac/commit/56bd7ec5ed904666074492f2e4f13e4fce226bee) | ||||||
|  | * Compat Config: Add missing config: email_lai_sec_interval (https://github.com/slawkens/myaac/commit/2eae44e0755e624a91be68b4d1ec26d01eb4d9a1) | ||||||
|  |  | ||||||
|  | ## [1.8.2 - 26.09.2025] | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * Routes: Possibility to override routes with plugins pages, like characters.php - No need to define routes in plugin.json anymore (https://github.com/slawkens/myaac/commit/3f24f961b1cdeff5c60387e837ae454448bc5e1b) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Style: Better look for myaac-table (https://github.com/slawkens/myaac/commit/a6032093b21e5bb3f0e75d2704da87d6dea6469d, https://github.com/slawkens/myaac/commit/5aa9bbf1c8e580d973ec82ac012489f8e7bc437e) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Install: Fix when config.local.php cannot be saved (https://github.com/slawkens/myaac/commit/4eab805d26d8c5562b29ed699769919d77dabced) | ||||||
|  | * Create Account: Fix an exception when email cannot be sent (https://github.com/slawkens/myaac/commit/d0112d1a67e8b854b65ad131f0375b79305df8d3) | ||||||
|  | * Login Page: Add missing csrf() - fix create account button (https://github.com/slawkens/myaac/commit/3c0cb53e17dd0b85394cfa0fdc9cf9ad8d4551df) | ||||||
|  | * tibiacom template: Fix account lost menu (https://github.com/slawkens/myaac/commit/ed9beaf2b6ca069e304e569c52e5b9188b58f05c) | ||||||
|  | * tibiacom template: Fix Menu div wrong tag/closing (#329) (https://github.com/slawkens/myaac/commit/85e7005fd3f0be51466151a3c122b96085fdfe68) | ||||||
|  | * tibiacom template: Replace firstChild with firstElementChild (Thanks to @un000000) (https://github.com/slawkens/myaac/commit/df7b6e29fb8875da97f431468c81ee99116271d9) | ||||||
|  |  | ||||||
|  | ## [1.8.1 - 05.09.2025] | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * New Commands: plugin:enable/disable/uninstall {plugin-name} (https://github.com/slawkens/myaac/commit/7a08f91d3fc0897c1ff76089ef3c649a2c6d2003, https://github.com/slawkens/myaac/commit/fec773ba4b740f35c0a3ef92ca8444a4c7d02082) | ||||||
|  | * Gifts: Added Transferable Coins to the store dropdown menu in the admin area (by @andreoam, #321) (https://github.com/slawkens/myaac/commit/42671c5c199dd9e91c774d8c9d30da9e12f1b695) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Commands: Allow settings to be changed/reset by plugin name (https://github.com/slawkens/myaac/commit/f8c4332e03e838d285ea0afb4b72b7c23e324d45, https://github.com/slawkens/myaac/commit/4b948e9510f7ba69d00f84d7fdaea8b3bf05b630) | ||||||
|  | * Templates: Menus should be saved for each template separately (https://github.com/slawkens/myaac/commit/482f4067b2a2e7513d9ba214274a361ffaf123d8) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Online: Fix skulls display (#320) (https://github.com/slawkens/myaac/commit/98073a110ae13f9592ec9d2c4d1d1aace87587a9) | ||||||
|  | * Online: Fix if there is no world_id in the server_record table (https://github.com/slawkens/myaac/commit/b6e1620f14c20eecfc9001a7d86dfb67942985c6) (Reported by @gesior in #318) | ||||||
|  | * tibiacom: some fixes to menus (https://github.com/slawkens/myaac/commit/20f99903ae80c74ad66c1cf5a5ea8d0b0fc2fd70, https://github.com/slawkens/myaac/commit/11dae90fa94fbbf47447017db5e5847c33d6aadf) | ||||||
|  | * Guilds: Fix for some servers that don't have guild_invites table (https://github.com/slawkens/myaac/commit/9725a3c2bdb7003f5cb48febb77604c31a9b805b) | ||||||
|  |  | ||||||
|  | ## [1.8 - 02.08.2025] | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * Templates - Kathrine: Possibility to add custom menu categories (https://github.com/slawkens/myaac/commit/ec11c1402417c25980582467546d1c1e9bb8267f) | ||||||
|  | * Admin Panel - Accounts Editor: Add Coins Transferable (https://github.com/slawkens/myaac/commit/45d6047031c9c3a0e7e512dc5d15c75629aec5a2, https://github.com/slawkens/myaac/commit/bb097b69ce106500a49686d6f4fe604348eaa310) | ||||||
|  | * Highscores: | ||||||
|  |   * Revamped: (https://github.com/slawkens/myaac/commit/d8132d4d76e03d5aa0c042be426320655a601392) | ||||||
|  |     * Show real rank, if 2 or more players have the same skill, show them with same rank | ||||||
|  |     * New setting: highscores_online_status | ||||||
|  |     * Additional fields passed to twig: updatedAt, totalResults, page, baseLink | ||||||
|  |   * Add new Setting: Display Skills Box (https://github.com/slawkens/myaac/commit/36ca755243ef1c83f6ac87465b426d4d8d3b0bb9) | ||||||
|  | * Functions: Add getExperienceForLevel (level) (https://github.com/slawkens/myaac/commit/1566deb84a082176b8c683fda205d828bc38fbcc) | ||||||
|  | * Commands - cache:clear : Add warning about APCu clear in CLI (https://github.com/slawkens/myaac/commit/83f84172e02e8ea2ccb6dca29bc033e44c35aebc) | ||||||
|  | * Models - PlayerOnline: Add missing $fillable into model (https://github.com/slawkens/myaac/commit/43415cf35db1c1307f2684c1728693d65065ffff) | ||||||
|  | * Twig: add cache variable (https://github.com/slawkens/myaac/commit/0efe47ce71c4b364a9e96bc5a55b1655326ae6da) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * pages/online: add cache, resulting in 20x performance boost | ||||||
|  |   * (for an example server with 2k players) (https://github.com/slawkens/myaac/commit/c8363086015cbb6e8786c398c7b9ac3959a26ec4) | ||||||
|  | * Admin Bar: Move admin bar code into body_start place_holder (https://github.com/slawkens/myaac/commit/f17269e44ce9dd38447bd2e2a8e1bdb065d4161f) | ||||||
|  | * Cache::remember: $ttl = 0 means no cache (https://github.com/slawkens/myaac/commit/3b47e9df2f4051807c5ff87892f7fa3d348f9c55) | ||||||
|  | * Templates: Load config.ini with $process_sections set to true (https://github.com/slawkens/myaac/commit/a89f9a84847630eb75b4890fdcc8b7a7bfa6b8ac) | ||||||
|  | * Twig: Allow for timestamp as integer in the timeago twig function | ||||||
|  |   (https://github.com/slawkens/myaac/commit/34fead906ea13b9f09d7a3c41ed88109d34d386c) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Settings: Fixed two exceptions (https://github.com/slawkens/myaac/commit/6e5a4ff8c78ff5373aba091baa66cae029557643, https://github.com/slawkens/myaac/commit/20d69a641c0a933d14889a89da6d32f6a4bc6c7d) | ||||||
|  | * Models\Account + OTS_Account -> isPremium -> ignore config.freePremium (https://github.com/slawkens/myaac/commit/5271633bdbfbbfed0b1d59c403093ce6fc2b7d20) | ||||||
|  | * Admin Panel - Mailer: | ||||||
|  |   * Fix send to email link redirecting from accounts page (https://github.com/slawkens/myaac/commit/080cc2781f034c844af658229e495e9a47fd2298) | ||||||
|  |   * Option to send only to verified accounts - only if setting('core.account_mail_verify') enabled (https://github.com/slawkens/myaac/commit/cf7fd20452e863980045bb5d6012ec86c6e8e01f) | ||||||
|  |  | ||||||
|  | ### Internal | ||||||
|  | * Rewrite to use constants (account transferable coins) (https://github.com/slawkens/myaac/commit/bccf8e056df985bbe1bab5f7ab5492f714d6b62b) | ||||||
|  | * Refactor to use HAS_ACCOUNT_COINS (https://github.com/slawkens/myaac/commit/caf326a6584a234775ebc6c8000ea02b3fecd160) | ||||||
|  |  | ||||||
|  | ## [1.7.1 - 27.06.2025] | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Rename plugin:install:install to plugin:setup, also add alias to previous command (https://github.com/slawkens/myaac/commit/13d33822b59df349199e885a78a3d6beb0863d0b) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Fix commands: setup + cache:clear (https://github.com/slawkens/myaac/commit/0da524fefe93b3028392e9014550eea3324d3a22, https://github.com/slawkens/myaac/commit/fe8281594e989f00280ba1adc734a9198c6b5cc1) | ||||||
|  | * Fix polls link in tibiacom template (https://github.com/slawkens/myaac/commit/d90fa323d7c77d81768df60feeb1c374b1650a0c) | ||||||
|  |  | ||||||
|  | ## [1.7 - 22.06.2025] | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * Feature: plugins versions check (#310) | ||||||
|  | * New hooks: HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS, HOOK_GUILDS_AFTER_MANAGE_BUTTON (https://github.com/slawkens/myaac/commit/c074a48f245df55646b6705737f667b6a84149b2, https://github.com/slawkens/myaac/commit/e6100a1b72de8695bba1dae9ba4e28bfdce47b10) | ||||||
|  | * Add OTS_Toolbox::getVocationName(id, promotion) + OTS_Player->isNameLocked() (https://github.com/slawkens/myaac/commit/e222957893c4a1de0dc8dbba55bce1a43418d275, https://github.com/slawkens/myaac/commit/522f6c11d835afd36fd07a07074d96d7e219b488) | ||||||
|  | * Add missing csrf in more places, causing white page with error about Request (https://github.com/slawkens/myaac/commit/dca904e61d21d856bf809070e7652803a2df0f58, https://github.com/slawkens/myaac/commit/c720ccc451ff90ef40b2a1595468d061ffd7e1e4) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Revamped online page (https://github.com/slawkens/myaac/commit/9a90e4aae280e607430511c6727d9a714b11f4c5, https://github.com/slawkens/myaac/commit/4767120043b09141870383e249f3729638d53dc2) | ||||||
|  | * Better $title inventing (https://github.com/slawkens/myaac/commit/0c95bcfd06b68b21512e477646ef7bd3a0d4912b) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Use apcu cache clear (https://github.com/slawkens/myaac/commit/b329da52aae9d0e21120a6444d3caf442420ce50, https://github.com/slawkens/myaac/commit/566c2a9151ab6392286f74e26853faa19a1b4f24) | ||||||
|  | * fix: boostedcreatures for 13.40 (by @GooseWithAKnife) (#307) | ||||||
|  |  | ||||||
|  | ## [1.6.1 - 11.06.2025] | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Fixed "Request has been cancelled due to security reasons", cause of missing csrf() in twig files (https://github.com/slawkens/myaac/commit/10cd71a6630ffec91b43a26a6d685b66c5836a6a) | ||||||
|  | * Fix: Ignore duplicated route exception (https://github.com/slawkens/myaac/commit/9d8e9d27bd87167d8d4005942a6af62bfe4c0892) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Move counter & visitors code before router (In case someone wants to include that info on page) (https://github.com/slawkens/myaac/commit/f78285030708ad3c74ab048711f73bbf3ee5281e) | ||||||
|  | * Set TinyMCE license key to gpl (Avoid warning message in browser console) (https://github.com/slawkens/myaac/commit/8d29fdb98b92dbc3d2853ef88a185c67036b4a77) | ||||||
|  |  | ||||||
|  | ### Removed | ||||||
|  | * Remove deprecated TinyMCE plugin - template (https://github.com/slawkens/myaac/commit/309c1fb715b882e67cb673b1544a03befbf64a22) | ||||||
|  |  | ||||||
|  | ## [1.6 - 03.06.2025] | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * Add new setting/configurable: site_url, prevents domain spoofing (https://github.com/slawkens/myaac/commit/d8a6090be382c35c19117cfef964b594ed02b8d4) | ||||||
|  | * Add new account coins setting (https://github.com/slawkens/myaac/commit/28886551e86fe562172c4c7f2afb89a2e7672c2e) | ||||||
|  | * autoload: settings/install/init.php (https://github.com/slawkens/myaac/commit/e5749437074c3b3556628a2aeb5bad2edf97bde0, https://github.com/slawkens/myaac/commit/7d213f479a7e40c6254069b5fc4e578dc32bf8d9, https://github.com/slawkens/myaac/commit/207d6bc69120aba1af2b51808f17e0059b571fed) | ||||||
|  | * Protect against csrf in more places (accounts & guilds & forums pages) (https://github.com/slawkens/myaac/commit/6eda38603c8ed7e99b92a78a4600b1245377f74d, https://github.com/slawkens/myaac/commit/e776bd52beb3064a9e694efd1b9021ec972ee2f6, https://github.com/slawkens/myaac/commit/84d502bf105f2a789481fba1acc820d236b4de66) | ||||||
|  | * Added two new hooks for pages loaded from database (custom pages): HOOK_BEFORE_PAGE_CUSTOM, HOOK_AFTER_PAGE_CUSTOM (https://github.com/slawkens/myaac/commit/c961a1ebf837f2ab1734a825ff2c57b4937610c9) | ||||||
|  | * Add global variables into $hooks->executeFilter (https://github.com/slawkens/myaac/commit/8fdea943768b20193eede99d60313ee84511a0be) | ||||||
|  | * Add getNPCsCount() to OTS_InfoRespond (https://github.com/slawkens/myaac/commit/7d435ff6433ef1fb2295ee79ed043ee10dc725e9) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Allow [] in character name (https://github.com/slawkens/myaac/commit/de6603a51347b9e656c58637ed9971fffdd7cedd) | ||||||
|  | * Do not allow access to tools/ folder after install (https://github.com/slawkens/myaac/commit/6e0f5913831f8dba69fd2d1505be3e2a303c6324) | ||||||
|  | * Fix CHANGELOG-1.x.md loading in admin panel (https://github.com/slawkens/myaac/commit/4a30fb495dbfbe1d434e8d52419eaf44fe517aee) | ||||||
|  | * Fix links not working in admin dashboard modules (https://github.com/slawkens/myaac/commit/be7b27c31aa3bbd6c0289c34d1e61139a3fe015c) | ||||||
|  | * Fix twig variables: logged + account_logged being not set directly after login (https://github.com/slawkens/myaac/commit/1e9b10d6489c488cadf7f6ed17b42f1ea6c767a8) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * OTS_ServerInfo -> move setTimeout out of class - Possibility to use the class without MyAAC (https://github.com/slawkens/myaac/commit/40d65a6613149fda51bdceb82c807e5301a3388b) | ||||||
|  |  | ||||||
|  | ## [1.5 - 14.05.2025] | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * Feature/twig hooks filters (#258) | ||||||
|  | * Add latest client versions (14.00 - 15.01) (https://github.com/slawkens/myaac/commit/5367df23812c6182863353c9a39fd7fb0b743f4b) | ||||||
|  | * db variable to twig (https://github.com/slawkens/myaac/commit/5ed1aec28e146b871a75597411d12e42a067f4e6) | ||||||
|  | * New filter: HOOK_FILTER_ROUTES (https://github.com/slawkens/myaac/commit/9b75011224f385db8b27e109bfeb28e75b9d779c) | ||||||
|  | * Allow optionally separate folder for views (thanks @Scrollog for idea) (https://github.com/slawkens/myaac/commit/03e275213901a89edb0ebb8974b776a992ab391f) | ||||||
|  | * Add float & double types to the Settings (https://github.com/slawkens/myaac/commit/67ab425bb9796d9d123296e3fda542fa8f7f05ee) | ||||||
|  | * Add optional param _page_only for single-page apps etc. (https://github.com/slawkens/myaac/commit/113473f2560aab6d364c301cc14a8b5ba8f309f4) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Change OTS_Account->getPremDays to not return -1 in case of freePremium (https://github.com/slawkens/myaac/commit/3befde2a1e4d24a011311e785f15185db57e19b8) | ||||||
|  | * Add note about highscores being updated x minutes + allow ttl 0 to disable cache (https://github.com/slawkens/myaac/commit/a161cff00329da6f970f3a70967fe8346fe92bbc) | ||||||
|  | * Better monster images (no image not found anymore) + use cache (https://github.com/slawkens/myaac/commit/73a5829974ceca3f02d7925d5cfbd5fa50b1bbd2) | ||||||
|  | * Rename server-info -> ots-info, changelog -> change-log (Due to conflict with apache2 server-info mod) (https://github.com/slawkens/myaac/commit/3949d84e5d7631f332111b6d00278bddbd0ad10a) | ||||||
|  | * Move rules page to admin panel (https://github.com/slawkens/myaac/commit/3949d84e5d7631f332111b6d00278bddbd0ad10a) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * php 8.4 warnings | ||||||
|  | * Visitors counter not working properly on dev mode (https://github.com/slawkens/myaac/commit/da151051186c913dd0dd091aabe893649c2b9ee7) | ||||||
|  | * Fix login.php boosted creature & boss (not sure exact version, but should be 14.12 or around) (https://github.com/slawkens/myaac/commit/c48b8006319f6c3b5f082befd16785420bb98110) | ||||||
|  | * Fix installMenus when theme/template was removed from disc (https://github.com/slawkens/myaac/commit/c24c580796bccd54bf9e95b864763f4642684d55) | ||||||
|  | * Fix if user removes the menu category (https://github.com/slawkens/myaac/commit/dbea69f31478391dacfbbc02c8353c39b4245daf) | ||||||
|  |  | ||||||
|  | ### Updated: | ||||||
|  | * Update cypress from version ^13.17.0 to ^14.3.3 (https://github.com/slawkens/myaac/commit/629fd18ea166860d5898a822f44f9277da6ce43d) | ||||||
|  |  | ||||||
|  | ## [1.4 - 22.04.2025] | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * feat: admin-pages (can add admin pages through plugins) (https://github.com/slawkens/myaac/commit/ceaa0639e66d31e8177ff90791463470367aa45d) | ||||||
|  | 	* just place the page in admin-pages folder in the plugin | ||||||
|  | 	* Also, possibility to overwrite default myaac admin pages | ||||||
|  | * Add db->hasTableAndColumns(table, columns), credits to @opentibiabr Team (https://github.com/slawkens/myaac/commit/82a533d88c8a342076891d132b4b409ed9a1fe72) | ||||||
|  | * Add noSubmit option to buttons.base (https://github.com/slawkens/myaac/commit/64f6d3abcada3bf9fd7599f50d2fac0a1367f383) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Fix: display 404 error instead of 500 when page has been removed from filesystem (https://github.com/slawkens/myaac/commit/c2bf94fb2370d2009a2eb907f818955132cf8611) | ||||||
|  | * Fix headline.php: change image format to .png cause of black background (https://github.com/slawkens/myaac/commit/b618084d50918539d9a70abd97e764137b966067) | ||||||
|  | * Clear cache on plugin enable/disable, fixes some issues with plugin pages being cached (https://github.com/slawkens/myaac/commit/1d0c173e7d000aecbd432800941fc3e38a0e50f2) | ||||||
|  | * Do not autoload sub-folders if autoload pages is disabled (https://github.com/slawkens/myaac/commit/d47195a7878095336f9c9edc6f96244257f67eec) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * SQL Syntax Standardization (by @JoaozinhoBrasil, #298) | ||||||
|  | * Pages in theme/template folder will now have precedence over normal pages (https://github.com/slawkens/myaac/commit/6d8f4718a1d349fba8f0ebc39cfd3a1a84d104b0) | ||||||
|  | * Small changes in account.login.html.twig (https://github.com/slawkens/myaac/commit/f40b986b59d4c8fa89ab4745731bf366f8619976) | ||||||
|  | * Plugin name is required, version is optional (https://github.com/slawkens/myaac/commit/e6f05a2731c61d931be49e121c068e49c0ad5e01) | ||||||
|  |  | ||||||
|  | ## [1.3.3 - 04.04.2025] | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Fix uninstall plugin when plugin is disabled (https://github.com/slawkens/myaac/commit/6c568fd36a271270684fc412ccd556b230273a6d) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Display more useful info when error parsing config.lua (https://github.com/slawkens/myaac/commit/fa6b6aa153ffc131e0d1631a4dcd9012a5850c2e) | ||||||
|  |  | ||||||
|  | ### Other | ||||||
|  | * Small adjustments (https://github.com/slawkens/myaac/commit/35e2483de86e295bdf089cceffa25842eeb2e34c, https://github.com/slawkens/myaac/commit/ae639d65b0bfa491e747e907e2ebc77f83f47981) | ||||||
|  |  | ||||||
|  | ## [1.3.2 - 01.04.2025] | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Fix debugBar/admin panel menu when using custom base_dir (https://github.com/slawkens/myaac/commit/65696f63e3aac02ff952ea81279e7cb2fa7570fb) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Settings: Show/hide IP Ban Protection options depending on the value (enabled/disabled) (https://github.com/slawkens/myaac/commit/dbf73d0b61b45601ae95e51b23c051c2704169c5) | ||||||
|  | * Do not require init.php in cache:clear command (https://github.com/slawkens/myaac/commit/d25c71857f767834239bbffacd00fdc671adb157) | ||||||
|  |  | ||||||
|  | ## [1.3.1 - 19.03.2025] | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Fixed migrate:run command (https://github.com/slawkens/myaac/commit/1a5771ad51e595fe13368a0721b059c4ecefb17d) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Small adjustments (https://github.com/slawkens/myaac/commit/6fac883659f581baac1361826d046410156f1e58, https://github.com/slawkens/myaac/commit/4a6896b4469968b9904292734cf6c14ba5eeef14) | ||||||
|  |  | ||||||
|  | ## [1.3 - 10.03.2025] | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Use latest outfit-images host from @gesior (https://github.com/slawkens/myaac/commit/529bdcf016dd0f9dffbc34d81f99a046a9ddb70d) | ||||||
|  | * Change monster link to $_GET ?name= (https://github.com/slawkens/myaac/commit/4c5cc8b573b2b3e7ec00a22b7ede30a68083a924) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Fixed house links (https://github.com/slawkens/myaac/commit/887b5068ad11c4cdab614afd34525caba785ce13) | ||||||
|  | * Fixed long title on headline.php (https://github.com/slawkens/myaac/commit/3e3f4bb5a514158ec8777684ca6c7f1c2a37bed5) | ||||||
|  | * Fixed menu colors once again, plus add !important tag (https://github.com/slawkens/myaac/commit/aa52df6e2ec92cafc25b655ae907bf2e1746d9cc) | ||||||
|  | * Fix: add possibility to remove all menu items in admin panel (https://github.com/slawkens/myaac/commit/00fe1adc15ea7646596d755f6e6e1f7854ffc1d5, https://github.com/slawkens/myaac/commit/9239a4f4198c3ad260802ac3b47e9c41b80b754e) | ||||||
|  |  | ||||||
|  | ## [1.2 - 09.02.2025] | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * Twig session(key) function + reworked session functions to accept multi-array like in Laravel (https://github.com/slawkens/myaac/commit/b46ddb43d03ef7e5fc34e555e92e856bdc905691) | ||||||
|  | * add template_name to twig variables (https://github.com/slawkens/myaac/commit/ae1161d77050bda181802b4496c9de920a7bb1bc) | ||||||
|  | * add HOOK_INIT, executed just after $hooks are loaded (https://github.com/slawkens/myaac/commit/19686725dc810f63a07f049f82c66cf336d90ca6) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * settings: password input hide/show, enable Save button only if changes has been made, save settings in transaction (https://github.com/slawkens/myaac/commit/4fda4f643b60a151179e5dd4f04912fb2618d98f, https://github.com/slawkens/myaac/commit/28fef952f857b79d64bc7495ffa5e1999e68e192, https://github.com/slawkens/myaac/commit/4b6024dc451accadb6c469fa282a9a764c1c0a81) | ||||||
|  | * rework menus: Different categories can have different colors + Option to reset menus (https://github.com/slawkens/myaac/commit/73de93a561f6b13111e019075724357d8a617249, https://github.com/slawkens/myaac/commit/3da3e62c5b12390d75de9b3320729bcca6e0b458) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * highscores: Fix online status + vocation for TFS 0.x (https://github.com/slawkens/myaac/commit/ea51ad27c38be88d86514cb979bb394fcfbef1f0) | ||||||
|  | * clear cache button in admin bar needed to be clicked twice until it worked (https://github.com/slawkens/myaac/commit/ea51ad27c38be88d86514cb979bb394fcfbef1f0) | ||||||
|  | * HOOK_STARTUP location (https://github.com/slawkens/myaac/commit/a73fb1003ee3f812cf182d1834d65f08e6f60d1f) | ||||||
|  | * if vocation name has more words (https://github.com/slawkens/myaac/commit/9d7fc98e1e0a96b59ecc1a7c39800a64445db364) | ||||||
|  |  | ||||||
|  | ### Updated | ||||||
|  | * Bump twig/twig from 3.18.0 to 3.19.0 (#284) | ||||||
|  |  | ||||||
|  | ## [1.1 - 27.01.2025] | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * adjust mailer settings descriptions to latest gmail (https://github.com/slawkens/myaac/commit/c5d5bb80671db135e6b503f53684771c7272e05d) | ||||||
|  | * optimize $player->isOnline() function, thanks @gesior (https://github.com/slawkens/myaac/commit/10dd818b139d5e1bb1ca9ec81edfb083ba9316b4) | ||||||
|  | * make players.comment and guilds.description VARCHAR (https://github.com/slawkens/myaac/commit/a45ceab83a74bee2b89cdb72baceda75e577e3cf) | ||||||
|  | * add lua/ folder to .gitignore (https://github.com/slawkens/myaac/commit/07012f786b1114cb6ab2f064f82c645b136a375a) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * general fixes in the tibiacom template menus, better support for custom menus | ||||||
|  | * make functions_custom.php optional (https://github.com/slawkens/myaac/commit/dc2b5afd9980984e2b259c9fc99f2ade46f70a5a) | ||||||
|  | * error in CLI, where BASE_URL is not defined (https://github.com/slawkens/myaac/commit/4d749b881582f64b5a46196dbbb5ee8097127f03) | ||||||
|  | * hook ACCOUNT_LOGIN_BEFORE_ACCOUNT location (https://github.com/slawkens/myaac/commit/669c447fca8643ce56d9ef8c1374ec647c780998) | ||||||
|  |  | ||||||
|  | ## [1.0.1 - 14.01.2025] | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * tibiacom account & news menu links not auto expanding | ||||||
|  |  | ||||||
|  | ### Updated (Thanks dependabot) | ||||||
|  | * twig from ^2.0 to ^3.11 | ||||||
|  | * tinymce from ^6.8.3 to ^7.2.0 | ||||||
|  | * cypress from ^12.12.0 to ^13.17.0 | ||||||
|  | * nesbot/carbon from 2.72.5 to 2.72.6 | ||||||
|  |  | ||||||
|  | ## [1.0 - 12.01.2025] | ||||||
|  |  | ||||||
|  | First stable release in the v1.0 series. | ||||||
|  |  | ||||||
|  | Minimum PHP 8.1 is required. | ||||||
|  |  | ||||||
|  | Changes since RC.2: | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * feature: migrations up/down. Allows to downgrade/upgrade database to specified version (https://github.com/slawkens/myaac/commit/3f6ff3a3326b0475d28d11ffd7fff51f362d799f) | ||||||
|  | * new hooks for news management (https://github.com/slawkens/myaac/commit/011a85d8ae34283ded6999882833f9d4797028ec, https://github.com/slawkens/myaac/commit/36bd3eb846e829b45313e10f7568dc4e95841143) | ||||||
|  | * None Vocation to highscores (can be changed to RookStayer in Admin Panel) (https://github.com/slawkens/myaac/commit/a4a248099521bb5b8b2aa5bd592138debd2f19d5) | ||||||
|  | * support for button_color (green, red, blue) (https://github.com/slawkens/myaac/commit/d8b6b749ee62e88b6af4a05d3d7557f90b94d94e) | ||||||
|  | * add $whoopsHandler as variable, can be used by plugins (https://github.com/slawkens/myaac/commit/b0c8cf2ecda23045d725aaf43cfb3852ed766a4b) | ||||||
|  | * PlayerModel->outfit_url attribute (https://github.com/slawkens/myaac/commit/3b5be1a8db5dceecaa388e2925a5536d13b38881) | ||||||
|  | * support for selecting plugin themes in Admin menus.php (https://github.com/slawkens/myaac/commit/77a2c1cec343ffe4be5c2c2503ee81bc32a14ca1) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * schema: Change character set to utf8mb4 (support for Emojis in Menus/Pages/News/Forum etc.) (https://github.com/slawkens/myaac/commit/27c44f1bdfb6234cf0c9d5b4b491123bb205b08f) | ||||||
|  | * prefer get_browser_real_ip() over REMOTE_ADDR (https://github.com/slawkens/myaac/commit/941846605c00cee83168d2f916410b8ba8d4b7b9) | ||||||
|  | * automatically set selected current one on highscores filters (https://github.com/slawkens/myaac/commit/e96227fbe41ae281783b2d49edb169a603601813) | ||||||
|  | * rewrite towns loading code, removed OTBM loader (was too slow) (https://github.com/slawkens/myaac/commit/c980a0914632e7b27f718464f669a200707d217e) | ||||||
|  | * allow OTS_Player to be passed as object to getPlayerLink (https://github.com/slawkens/myaac/commit/84d37c5a8f2c4535a41c8aa8264752969d3f3a3d) | ||||||
|  | * do not clear menus by default on install (https://github.com/slawkens/myaac/commit/12d8faa3eda5e798f97b71e941c035187daad96e) | ||||||
|  | * display warning in admin panel - plugins - if zip extension is not installed (https://github.com/slawkens/myaac/commit/e3ffe5d9e11d78ab064a370d8541bac351c9bcd9) | ||||||
|  | * set default_socket_timeout for ipinfo.io checkup to 5 seconds (https://github.com/slawkens/myaac/commit/783d96fc6568a607d3198b832fed3a0dd06c4ebb) | ||||||
|  | * refactor getTopPlayers function (support for balance) (https://github.com/slawkens/myaac/commit/c769962e39fe8dfb72ecd5be1864e145696be794) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * XSS in forum (https://github.com/slawkens/myaac/commit/c2b7286d20d4b579171540f7a774e8a0995d5e8f, https://github.com/slawkens/myaac/commit/8fb643596f9586005976e7bdb484a541a9d8715e) | ||||||
|  | * price deducted when changing sex (https://github.com/slawkens/myaac/commit/16671ea40b72dcf74037c359ad572f9eb825edf9) | ||||||
|  | * move_thread by unauthorized user (https://github.com/slawkens/myaac/commit/d6c40c836a53cb1710f911f77f45f28b54ea1b54, thanks @anyeor) | ||||||
|  | * TFS 1.4.2 where conditions is NULL (https://github.com/slawkens/myaac/commit/b8396d4c8482e951da538b13f2296123732c4545) | ||||||
|  | * do not show forum new thread show button if not logged in (https://github.com/slawkens/myaac/commit/507402171ba3b6e7ee184bd7fa73e0d55e0cad7a, @anyeor) | ||||||
|  | * login if limiter is disabled (https://github.com/slawkens/myaac/commit/a0f1971583f0f790013e2145fb5ac573c59fbdef) | ||||||
|  | * fixes to installMenus function (https://github.com/slawkens/myaac/commit/a2fadc5945fe0a5e39f740827f6ffbda1bb501e2) | ||||||
|  | * many PHP exceptions in different places | ||||||
|  | * fixes to tibiacom menus ActiveSubmenuItem | ||||||
|  |  | ||||||
|  | ### Removed | ||||||
|  | * bugtracker SQL table code as the page has been removed/moved to plugins (https://github.com/slawkens/myaac/commit/5782772b901b05fb814bc718d062f6e2cd71df8c) | ||||||
|  |  | ||||||
|  | ## [1.0-RC.2 - 25.10.2024] | ||||||
|  |  | ||||||
|  | Still waiting for your reports about bugs found in this release. We are very close to stable release. | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * feat: rate limit settings for blocking accounts login attempts (@gpedro, #266) | ||||||
|  | * search by email in accounts editor (https://github.com/slawkens/myaac/commit/c2ec46824621468f2a1cb4046805c485ed13fea5) | ||||||
|  | * New hooks in account manage + create (https://github.com/slawkens/myaac/commit/93641fc68ac9a5f1479329e2bd41380c19534d5d) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * chore: drop raw queries + accounts - search by email + accounts - required min size for search by account number (@gpedro, #266) | ||||||
|  | * Use https for outfit & item images (https://github.com/slawkens/myaac/commit/71c00aa5e01fbdfd88802912e200dd1025976231) | ||||||
|  | * Do not require players & guilds tables on install (https://github.com/slawkens/myaac/commit/779aa152fa940261c9b161533946f44e288597a2) | ||||||
|  | * Do not create player if there is no players table in db (https://github.com/slawkens/myaac/commit/201f95caa8b70e88fa651eac8c3c3aa7cd765bd0) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Highscore frags fixed for TFS 0.3 (@Scrollog, #263) | ||||||
|  | * Missing groups variable #262. thanks, @Scrollog for reporting (https://github.com/slawkens/myaac/commit/8d8bdb6dac6df21672ac77288fff2f2f8d6eb665) | ||||||
|  | * Verified email for login.php (@gpedro, #265) | ||||||
|  | * Warning if core.account_country is disabled (https://github.com/slawkens/myaac/commit/ab73d60c61e14a1cacdb6cfbf7f89f4bf3be0833) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## [1.0-RC.1 - 23.07.2024] | ||||||
|  |  | ||||||
|  | Changes since 1.0-beta: | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * Feat: Hooks priority (https://github.com/slawkens/myaac/commit/dc17b701da053e04bfa64e21be9247a4f07505e1) | ||||||
|  | * Make autoload of pages, commands and themes configurable (https://github.com/slawkens/myaac/commit/c1d4b4f80cd6bb85507ee9471e47013955a26a91) | ||||||
|  | * Fraggers in characters page for TFS 1.x and canary (https://github.com/slawkens/myaac/commit/42f99c3edc8de39cccc5632cb42e88b24579c5a6) | ||||||
|  | * New hooks: HOOK_INSTALL_FINISH, HOOK_ACCOUNT_CREATE_CHARACTER_* (https://github.com/slawkens/myaac/commit/08ac8ebade106521a5c7396faa5ce7006e629f7c, https://github.com/slawkens/myaac/commit/45dda5e834ff2059faea6ef9be2efa76f1723cbd) | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Allow account_create_character_create even if account_mail_verify is activated (https://github.com/slawkens/myaac/commit/203e411b626fe62401a4b74a48420769e512aa39) | ||||||
|  | * Create guild_rank entries, in case MySQL trigger not loaded (https://github.com/slawkens/myaac/commit/d9c1b2507c81f306970642b35e4bf5f7cc04a6f2, https://github.com/slawkens/myaac/commit/47a19e85dd84e9f3b39a1b29cfc2c04b004832b9) | ||||||
|  | * Set Admin Account verified by default (https://github.com/slawkens/myaac/commit/cd49dfc79942f3301ce9c0b8d899b9f39bda9a41) | ||||||
|  | * Refactor account routes into sub folders (https://github.com/slawkens/myaac/commit/bdc0c43d3fd3a51030c3e916bdb9f008468f5ecd) | ||||||
|  | * Order towns by id (https://github.com/slawkens/myaac/commit/9ea2a5067fc4b75de395f381577b18914132ad84) | ||||||
|  | * Do not create news about myaac, if any news already exist (on installation (https://github.com/slawkens/myaac/commit/504242fb846b73b56b87bc1e39d070687ad7f5b4) | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * Not working google recaptcha plugin (https://github.com/slawkens/myaac/commit/a1bcb217ecf4e21fd58da4ba491da1852029898a) | ||||||
|  | * Not working account create if account_country is disabled (https://github.com/slawkens/myaac/commit/933b681a9fcdbb6283e0469b3806d2ded492d232) | ||||||
|  | * Account verify - do not allow login without verified email (Thanks @anyeor, https://github.com/slawkens/myaac/commit/fcb13f3c0fb8ceafda0bd614a229a26a269432bd) | ||||||
|  | * Detect tools/ext exists on install to prevent broken installs (https://github.com/slawkens/myaac/commit/10a739773c4f2911876bc802a0ee0537c3e00a92) | ||||||
|  | * Cache reloading each time page refreshes (https://github.com/slawkens/myaac/commit/ec96985872057340112f65073efc0c4bf86dddb0) | ||||||
|  | * Highscores frags for TFS 1.x and canary (https://github.com/slawkens/myaac/commit/a04d186c22912915f0a7873dfe677ef3b5a23c79) | ||||||
|  | * Monsters page: monster not found exception (https://github.com/slawkens/myaac/commit/ef79b99b8acc179f14b8475547347d9daca27512) | ||||||
|  | * Fixed bug if \<flags\> are not present in monster.xml (https://github.com/slawkens/myaac/commit/57b47ab7983f625c7c0ef4f5303a4d07ef172786) | ||||||
|  | * fastRoute duplicate errors (https://github.com/slawkens/myaac/commit/4c0739d3e93812dff0c33849ea3f38e4e49113ac) | ||||||
|  | * useGuildNick displaying (https://github.com/slawkens/myaac/commit/0db0ec1aa47e044c26bc403ff5078a2115d086f8) | ||||||
|  |  | ||||||
|  | ## [1.0-beta - 18.05.2024] | ||||||
|  |  | ||||||
|  | Minimum PHP version for this release is 8.1. | ||||||
|  |  | ||||||
|  | ### Added | ||||||
|  | * reworked Admin Panel (@Leesneaks, @gpedro, @slawkens) | ||||||
|  |   * updated to Bootstrap v4 | ||||||
|  |   * new Menu | ||||||
|  |   * new Dashboard: statistics, server status | ||||||
|  |   * new Admin Bar showed on top when admin logged in | ||||||
|  |   * new page: Server Data, to reload server data | ||||||
|  |     * Towns, NPCs & Items are stored in permanent cache | ||||||
|  |   * new pages: mass account & teleport tools | ||||||
|  |   * changelogs editor | ||||||
|  |   * revised Accounts & Players editors | ||||||
|  |   * option to add/modify admin menus with plugins | ||||||
|  |   * option to enable/disable plugins | ||||||
|  |   * better, updated TinyMCE editor (v6.x) | ||||||
|  |     * with option to upload images | ||||||
|  |   * list of open source libraries used in project page | ||||||
|  | * auto-loading of themes, commands & pages from plugins/ folder. You need just to place them in correct folder and they will be loaded automatically - this allows better customization, without interfering with core AAC folders. This will allow in the future automatic updates for plugins as well the AAC as whole. | ||||||
|  | * config.php moved to Admin Panel -> Settings page | ||||||
|  | * new console script: aac - using symfony/console | ||||||
|  |   * usage: `php aac` (will list all commands by default) | ||||||
|  |   * example: `php aac cache:clear` | ||||||
|  |   * example: `php aac plugin:install theme-example.zip` | ||||||
|  | * replace POT Query Builder to Eloquent ORM. Not 100% yet - in some places there is still old $db approach used (@gpedro) (https://github.com/slawkens/myaac/pull/230) | ||||||
|  | * brand new charming installation page (by @fernandomatos) | ||||||
|  |   * using Bootstrap | ||||||
|  | * new pages router: nikic/fast-route, allowing for better customisation | ||||||
|  | * Plugin cronjobs: central control of the cronjobs | ||||||
|  | * Guild Wars support (available as plugin) | ||||||
|  | * support for login and create account only by email (configurable) | ||||||
|  |   * with no need for account name | ||||||
|  | * Google ReCAPTCHA v3 support (available as plugin) | ||||||
|  | * support for Account Number | ||||||
|  |   * suggest account number option | ||||||
|  | * many new functions, hooks and configurables | ||||||
|  | * better Exception Handler (Whoops - https://github.com/filp/whoops) | ||||||
|  | * automated website tests (using Cypress) | ||||||
|  | * csrf protection (https://github.com/slawkens/myaac/pull/235) | ||||||
|  | * option to restrict Page view to specified group of users (Not-Logged in, logged-in players, tutors, gamemasters etc.) | ||||||
|  | * phpdebug bar (http://phpdebugbar.com/). Activated if env == 'dev', can be also activated in production by enabling "enable_debugbar" in local config | ||||||
|  |  | ||||||
|  | ### Changed | ||||||
|  | * Composer and NPM is now used for external libraries like: Twig, PHPMailer, fast-route, jQuery, Bootstrap etc. | ||||||
|  | * mail support is disabled on fresh install, can be manually enabled by user | ||||||
|  | * disable add php pages in admin panel for security. Option to disable plugins upload | ||||||
|  | * visitors counter shows now user browser, and also if its bot | ||||||
|  | * changes in required and optional PHP extensions | ||||||
|  | * reworked Pages: | ||||||
|  | 	* Bans | ||||||
|  | 		* works now for TFS 1.x | ||||||
|  | 	* Highscores | ||||||
|  | 		* frags works for TFS 1.x | ||||||
|  | 		* cached | ||||||
|  | 	* Monsters | ||||||
|  | * moved pages to Twig: | ||||||
|  |   * experience stages | ||||||
|  | * update player_deaths entries on name change | ||||||
|  | * change_password email to be more informal | ||||||
|  |  | ||||||
|  | ### Fixed | ||||||
|  | * hundreds of bug fixes, mostly patched from 0.8, so it makes no sense writing them again here | ||||||
							
								
								
									
										18
									
								
								CONTRIBUTORS.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,18 @@ | |||||||
|  | # automatically exported using this script: | ||||||
|  | # git log --all --format='%cN <%cE>' | sort -u > contributors | ||||||
|  | # in no particular order | ||||||
|  | # cleaned for readability | ||||||
|  |  | ||||||
|  | Evil Puncker <EPuncker@users.noreply.github.com> | ||||||
|  | Fernando Matos <fernando@pixele.com.br> | ||||||
|  | Lee <42119604+Leesneaks@users.noreply.github.com> | ||||||
|  | caio <caio.zucoli@gmail.com> | ||||||
|  | slawkens <slawkens@gmail.com> | ||||||
|  | tobi132 <tobi132@gmx.net> | ||||||
|  | vankk <nwtr.otland@hotmail.com> | ||||||
|  | whiteblXK <krzys16001@gmail.com> | ||||||
|  | xitobuh <jonas.hockert92@gmail.com> | ||||||
|  | Danilo Pucci <dnlps@hotmail.com> | ||||||
|  | gpedro <gpedro831@gmail.com> | ||||||
|  | Matheus Collier <matheuscollier@gmail.com> | ||||||
|  | SRNT-GG <95472530+SRNT-GG@users.noreply.github.com> | ||||||
							
								
								
									
										3
									
								
								CREDITS
									
									
									
									
									
								
							
							
						
						| @@ -1,2 +1,3 @@ | |||||||
| * Gesior.pl (2007 - 2008) | * Gesior.pl (2007 - 2008) | ||||||
| * Slawkens (2009 - 2017) | * Slawkens (2009 - 2025) | ||||||
|  | * Contributors listed in CONTRIBUTORS.txt | ||||||
|   | |||||||
							
								
								
									
										85
									
								
								README.md
									
									
									
									
									
								
							
							
						
						| @@ -1,18 +1,38 @@ | |||||||
| # myaac | # [MyAAC](https://my-aac.org) | ||||||
| MyAAC is a free and open-source Automatic Account Creator (AAC) and Content Management System (CMS) written in PHP. It is a fork of the [Gesior](https://github.com/gesior/Gesior2012) project. It supports only MySQL databases. |  | ||||||
|  | MyAAC is a free and open-source Automatic Account Creator (AAC) for Open Tibia Servers written in PHP. It is a fork of the [Gesior](https://github.com/gesior/Gesior2012) project. It supports only MySQL databases. | ||||||
|  |  | ||||||
| Official website: https://my-aac.org | Official website: https://my-aac.org | ||||||
|  |  | ||||||
| ### REQUIREMENTS | [](https://github.com/slawkens/myaac/actions) | ||||||
|  | [](https://opensource.org/licenses/gpl-license) | ||||||
|  | [](https://github.com/slawkens/myaac/releases) | ||||||
|  | [](https://discord.gg/2J39Wus) | ||||||
|  | [](https://github.com/slawkens/myaac/issues?q=is%3Aissue+is%3Aclosed) | ||||||
|  |  | ||||||
|  | | Version | Status                 | Branch  | Requirements   | | ||||||
|  | |:--------|:-----------------------|:--------|:---------------| | ||||||
|  | | 2.x     | Experimental features  | develop | PHP >= 8.1     | | ||||||
|  | | **1.x** | **Active development** | main    | **PHP >= 8.1** | | ||||||
|  | | 0.9.x   | Not developed anymore  | 0.9     | PHP >= 7.2.5   | | ||||||
|  | | 0.8.x   | Active support         | 0.8     | PHP >= 7.2.5   | | ||||||
|  | | 0.7.x   | End Of Life            | 0.7     | PHP >= 5.3.3   | | ||||||
|  |  | ||||||
|  | The recommended version to install is 1.x, which can be found at releases page - [https://github.com/slawkens/myaac/releases](https://github.com/slawkens/myaac/releases). | ||||||
|  |  | ||||||
|  | ### Documentation | ||||||
|  | * [docs.my-aac.org](https://docs.my-aac.org) | ||||||
|  | * [my-aac.org - FAQ](https://my-aac.org/faqs/) | ||||||
|  |  | ||||||
|  | ### Requirements | ||||||
|  |  | ||||||
| 	- PHP 5.3.0 or later |  | ||||||
| 	- MySQL database | 	- MySQL database | ||||||
| 	- PDO PHP Extension | 	- PHP Extensions: pdo, xml, json | ||||||
| 	- XML PHP Extension | 	- (optional) apache2 mod_rewrite (to use friendly_urls) | ||||||
| 	- ZIP PHP Extension | 	- (optional) zip PHP Extension (to install plugins) | ||||||
| 	- (optional) mod_rewrite to use friendly_urls | 	- (optional) gd PHP Extension (for generating signature images) | ||||||
|  |  | ||||||
| ### INSTALLATION AND CONFIGURATION | ### Installation | ||||||
|  |  | ||||||
| 	Just decompress and untar the source (which you should have done by now, | 	Just decompress and untar the source (which you should have done by now, | ||||||
| 	if you're reading this), into your webserver's document root. | 	if you're reading this), into your webserver's document root. | ||||||
| @@ -28,18 +48,51 @@ Official website: https://my-aac.org | |||||||
| 			chmod 660 images/guilds | 			chmod 660 images/guilds | ||||||
| 			chmod 660 images/houses | 			chmod 660 images/houses | ||||||
| 			chmod 660 images/gallery | 			chmod 660 images/gallery | ||||||
|  | 			chmod -R 760 system/cache | ||||||
|  |  | ||||||
| 	Visit http://your_domain/install (http://localhost/install) and follow instructions in the browser. | 	Visit http://your_domain/install (http://localhost/install) and follow instructions in the browser. | ||||||
|  |  | ||||||
| ### KNOWN PROBLEMS | ### Configuration | ||||||
|  |  | ||||||
| 	- none - | Check *config.php* to get more information. (Notice: MyAAC 1.0+ doesn't use config.php anymore, it has been moved to Admin Panel - Settings page). | ||||||
|  |  | ||||||
| ### OTHER NOTES | Use *config.local.php* for your local configuration changes. | ||||||
|  |  | ||||||
| 	If you have a great idea or want contribute to the project - visit our website at http://www.my-aac.org | ### Branches | ||||||
|  |  | ||||||
| ### LICENSING | This repository follows the Git Flow Workflow. | ||||||
|  | Cheatsheet: [Git-Flow-Cheatsheet](https://danielkummer.github.io/git-flow-cheatsheet) | ||||||
|  |  | ||||||
| 	This program and all associated files are released under the GNU Public | That means, we use: | ||||||
| 	License, see LICENSE for details. | * main branch, for current stable release | ||||||
|  | * develop branch, for development version (next release) | ||||||
|  | * feature branches, for features etc. | ||||||
|  |  | ||||||
|  | ### Known Problems | ||||||
|  |  | ||||||
|  | - Some compatibility issues with some exotic distributions. | ||||||
|  |  | ||||||
|  | ### Contributing | ||||||
|  |  | ||||||
|  | Contributions are more than welcome.  | ||||||
|  |  | ||||||
|  | Pull requests should be made to the *develop* branch as that is the working branch, master is for release code.   | ||||||
|  |  | ||||||
|  | Bug fixes to current release should be done to master branch. | ||||||
|  |  | ||||||
|  | Look: [Contributing](https://docs.my-aac.org/misc/contributing) in our wiki. | ||||||
|  |  | ||||||
|  | ### Other Notes | ||||||
|  |  | ||||||
|  | If you have a great idea or want to contribute to the project - visit our website at https://www.my-aac.org | ||||||
|  |  | ||||||
|  | ## Project supported by JetBrains | ||||||
|  |  | ||||||
|  | Many thanks to Jetbrains for kindly providing a license for me to work on this and other open-source projects. | ||||||
|  |  | ||||||
|  | [](https://www.jetbrains.com/?from=https://github.com/slawkens) | ||||||
|  |  | ||||||
|  | ### License | ||||||
|  |  | ||||||
|  | This program and all associated files are released under the GNU Public License.   | ||||||
|  | See [LICENSE](https://github.com/slawkens/myaac/blob/main/LICENSE) for details. | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								TODO
									
									
									
									
									
								
							
							
						
						| @@ -1,37 +0,0 @@ | |||||||
| // MyAAC TODO |  | ||||||
|  |  | ||||||
| 0.* |  | ||||||
| 	* support duplicated vocation names with different ids |  | ||||||
| 	* plugins: option to define custom requirements check in json file, to check if system meets the requirement |  | ||||||
| 	* add support for defining max myaac version in plugin.json file |  | ||||||
| 	* cache Menus in templates |  | ||||||
| 	* don't show error indicators on first time load - createaccount page |  | ||||||
| 	* update Twig to the latest version from 1.x branch |  | ||||||
| 	* semantic versioning support for plugins (github.com/composer/semver) |  | ||||||
| 	* add some notice to the user that installing step "Import Schema" will take some time |  | ||||||
| 	* check user IP on installing to prevent install by random user |  | ||||||
|  |  | ||||||
| 1.0: |  | ||||||
| 	* i18n support (issue #1 on github) |  | ||||||
| 	* New Admin Panel layout and interface |  | ||||||
| 	* add changelog management interface |  | ||||||
| 	* remove tibiacom template, and include it as a plugin |  | ||||||
|  |  | ||||||
| 2.0 |  | ||||||
| 	* remove compat functions |  | ||||||
| 	* folder restructure: |  | ||||||
| 		* var/ (for logs, cache and data), config/, bin, public/ (for index and images and other public content), system/ (for php files and classess) |  | ||||||
| 	* rename templates to layouts as templates is meant to be used for twig templates |  | ||||||
| 	* change gifts_system to shop_system configurable |  | ||||||
| 	* move most used options in system/templates dir to separate directories (more transparent) |  | ||||||
|  |  | ||||||
| At any time between (version not specified): |  | ||||||
| 	* better news archive with search function (like on tibia.com) |  | ||||||
| 	* guild wars management (issue #13 on github) |  | ||||||
| 	* update account.management page to be more realistic (like on tibia.com) |  | ||||||
| 	* update guilds page to be more realistic (like on tibia.com) |  | ||||||
| 	* possibility to add extra cache engines with plugins |  | ||||||
| 	* preferably configurable (enable/disable) forum TinyMCE editor |  | ||||||
| 	* new cache engine - plain php, is good with pure php 7.0+ and opcache |  | ||||||
| 	* OTAdmin support in Admin Panel |  | ||||||
| 	* database towns table support for TFS 1.3 |  | ||||||
							
								
								
									
										1
									
								
								_config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | |||||||
|  | theme: jekyll-theme-slate | ||||||
							
								
								
									
										38
									
								
								aac
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,38 @@ | |||||||
|  | #!/usr/bin/env php | ||||||
|  | <?php | ||||||
|  |  | ||||||
|  | require_once __DIR__ . '/common.php'; | ||||||
|  |  | ||||||
|  | if(!IS_CLI) { | ||||||
|  | 	echo 'This script can be run only in command line mode.'; | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | require_once SYSTEM . 'functions.php'; | ||||||
|  |  | ||||||
|  | define('SELF_NAME', basename(__FILE__)); | ||||||
|  |  | ||||||
|  | use MyAAC\Plugins; | ||||||
|  | use Symfony\Component\Console\Application; | ||||||
|  |  | ||||||
|  | $application = new Application('MyAAC', MYAAC_VERSION); | ||||||
|  |  | ||||||
|  | $commandsGlob = glob(SYSTEM . 'src/Commands/*.php'); | ||||||
|  | foreach ($commandsGlob as $item) { | ||||||
|  | 	$name = pathinfo($item, PATHINFO_FILENAME); | ||||||
|  | 	if ($name == 'Command') { // ignore base Command class | ||||||
|  | 		continue; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$commandPre = '\\MyAAC\Commands\\'; | ||||||
|  | 	if (!trait_exists($class = $commandPre . $name)) { | ||||||
|  | 		$application->add(new $class); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $pluginCommands = Plugins::getCommands(); | ||||||
|  | foreach ($pluginCommands as $item) { | ||||||
|  | 	$application->add(require $item); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $application->run(); | ||||||
							
								
								
									
										
											BIN
										
									
								
								admin/images/logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.3 KiB | 
							
								
								
									
										22
									
								
								admin/includes/debugbar.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,22 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $hooks->register('debugbar_admin_head_end', HOOK_ADMIN_HEAD_END, function ($params) { | ||||||
|  | 	global $debugBar; | ||||||
|  |  | ||||||
|  | 	if (!isset($debugBar)) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$debugBarRenderer = $debugBar->getJavascriptRenderer(BASE_URL . 'vendor/maximebf/debugbar/src/DebugBar/Resources/'); | ||||||
|  | 	echo $debugBarRenderer->renderHead(); | ||||||
|  | }); | ||||||
|  | $hooks->register('debugbar_admin_body_end', HOOK_ADMIN_BODY_END, function ($params) { | ||||||
|  | 	global $debugBar; | ||||||
|  |  | ||||||
|  | 	if (!isset($debugBar)) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$debugBarRenderer = $debugBar->getJavascriptRenderer(BASE_URL . 'vendor/maximebf/debugbar/src/DebugBar/Resources/'); | ||||||
|  | 	echo $debugBarRenderer->render(); | ||||||
|  | }); | ||||||
| @@ -1 +1,2 @@ | |||||||
| <?php | <?php | ||||||
|  | // nothing yet here | ||||||
							
								
								
									
										37
									
								
								admin/includes/settings_menus.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,37 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | use MyAAC\Plugins; | ||||||
|  |  | ||||||
|  | $order = 10; | ||||||
|  |  | ||||||
|  | $settingsMenu = []; | ||||||
|  |  | ||||||
|  | $settingsMenu[] = [ | ||||||
|  | 	'name' => 'MyAAC', | ||||||
|  | 	'link' => 'settings&plugin=core', | ||||||
|  | 	'icon' => 'list', | ||||||
|  | 	'order' => $order, | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | foreach (Plugins::getAllPluginsSettings() as $setting) { | ||||||
|  | 	$file = BASE . $setting['settingsFilename']; | ||||||
|  | 	if (!file_exists($file)) { | ||||||
|  | 		warning('Plugin setting: ' . $file . ' - cannot be loaded.'); | ||||||
|  | 		continue; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$order += 10; | ||||||
|  |  | ||||||
|  | 	$settings = require $file; | ||||||
|  |  | ||||||
|  | 	$settingsMenu[] = [ | ||||||
|  | 		'name' => $settings['name'], | ||||||
|  | 		'link' => 'settings&plugin=' . $setting['pluginFilename'], | ||||||
|  | 		'icon' => 'list', | ||||||
|  | 		'order' => $order, | ||||||
|  | 	]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | unset($settings, $file, $order); | ||||||
|  |  | ||||||
|  | return $settingsMenu; | ||||||
| @@ -1,54 +1,75 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| // few things we'll need | // few things we'll need | ||||||
| require('../common.php'); | use MyAAC\Plugins; | ||||||
| require_once(BASE . 'config.local.php'); |  | ||||||
|  | require '../common.php'; | ||||||
|  |  | ||||||
|  | const ADMIN_PANEL = true; | ||||||
|  | const MYAAC_ADMIN = true; | ||||||
|  |  | ||||||
| if(file_exists(BASE . 'install') && (!isset($config['installed']) || !$config['installed'])) | if(file_exists(BASE . 'install') && (!isset($config['installed']) || !$config['installed'])) | ||||||
| { | { | ||||||
| 	header('Location: ' . BASE_URL . 'install/'); | 	header('Location: ' . BASE_URL . 'install/'); | ||||||
| 	die('Setup detected that <b>install/</b> directory exists. Please visit <a href="' . BASE_URL . 'install">this</a> url to start MyAAC Installation.<br/>Delete <b>install/</b> directory if you already installed MyAAC.<br/>Remember to REFRESH this page when you\'re done!'); | 	throw new RuntimeException('Setup detected that <b>install/</b> directory exists. Please visit <a href="' . BASE_URL . 'install">this</a> url to start MyAAC Installation.<br/>Delete <b>install/</b> directory if you already installed MyAAC.<br/>Remember to REFRESH this page when you\'re done!'); | ||||||
| } | } | ||||||
|  |  | ||||||
| define('ADMIN_PANEL', true); |  | ||||||
|  |  | ||||||
| $content = ''; | $content = ''; | ||||||
|  |  | ||||||
| // validate page | // validate page | ||||||
| $page = isset($_GET['p']) ? $_GET['p'] : ''; | $page = $_GET['p'] ?? ''; | ||||||
| if(empty($page) || preg_match("/[^a-zA-Z0-9_\-]/", $page)) | if(empty($page) || preg_match("/[^a-zA-Z0-9_\-\/.]/", $page)) | ||||||
| 	$page = 'dashboard'; | 	$page = 'dashboard'; | ||||||
|  |  | ||||||
| $page = strtolower($page); | $page = strtolower($page); | ||||||
| define('PAGE', $page); | define('PAGE', $page); | ||||||
|  |  | ||||||
| require(SYSTEM . 'functions.php'); | require SYSTEM . 'functions.php'; | ||||||
| require(SYSTEM . 'init.php'); | require SYSTEM . 'init.php'; | ||||||
| require(SYSTEM . 'status.php'); |  | ||||||
| require(SYSTEM . 'login.php'); | require __DIR__ . '/includes/debugbar.php'; | ||||||
| require(ADMIN . 'includes/functions.php'); | require SYSTEM . 'status.php'; | ||||||
|  | require SYSTEM . 'login.php'; | ||||||
|  | require __DIR__ . '/includes/functions.php'; | ||||||
|  |  | ||||||
| $twig->addGlobal('config', $config); | $twig->addGlobal('config', $config); | ||||||
| $twig->addGlobal('status', $status); | $twig->addGlobal('status', $status); | ||||||
|  |  | ||||||
|  | if (ACTION == 'logout') { | ||||||
|  | 	require SYSTEM . 'logout.php'; | ||||||
|  | } | ||||||
|  |  | ||||||
| // if we're not logged in - show login box | // if we're not logged in - show login box | ||||||
| if(!$logged || !admin()) { | if(!$logged || !admin()) { | ||||||
| 	$page = 'login'; | 	$page = 'login'; | ||||||
| } | } | ||||||
|  |  | ||||||
| // include our page  | $pluginsAdminPages = Plugins::getAdminPages(); | ||||||
| $file = SYSTEM . 'pages/admin/' . $page . '.php'; | if(isset($pluginsAdminPages[$page]) && file_exists(BASE . $pluginsAdminPages[$page])) { | ||||||
| if(!@file_exists($file)) { | 	$file = BASE . $pluginsAdminPages[$page]; | ||||||
|  | } | ||||||
|  | else { | ||||||
|  | 	// include our page | ||||||
|  | 	$file = __DIR__ . '/pages/' . $page . '.php'; | ||||||
|  | 	if(!@file_exists($file)) { | ||||||
|  | 		if (str_contains($page, 'plugins/')) { | ||||||
|  | 			$file = BASE . $page; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
| 			$page = '404'; | 			$page = '404'; | ||||||
| 			$file = SYSTEM . 'pages/404.php'; | 			$file = SYSTEM . 'pages/404.php'; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| ob_start(); | ob_start(); | ||||||
| include($file); | if($hooks->trigger(HOOK_ADMIN_BEFORE_PAGE)) { | ||||||
|  | 	require $file; | ||||||
|  | } | ||||||
|  |  | ||||||
| $content .= ob_get_contents(); | $content .= ob_get_contents(); | ||||||
| ob_end_clean(); | ob_end_clean(); | ||||||
|  |  | ||||||
| // template | // template | ||||||
| $template_path = 'template/'; | $template_path = 'template/'; | ||||||
| require(ADMIN . $template_path . 'template.php'); | require __DIR__ . '/' . $template_path . 'template.php'; | ||||||
| ?> |  | ||||||
|   | |||||||
							
								
								
									
										674
									
								
								admin/pages/accounts.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,674 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Account editor | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Lee | ||||||
|  |  * @copyright 2020 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Account as AccountModel; | ||||||
|  | use MyAAC\Models\Player; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $title = 'Account editor'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | $admin_base = ADMIN_URL . '?p=accounts'; | ||||||
|  | $use_datatable = true; | ||||||
|  |  | ||||||
|  | if (setting('core.account_country')) | ||||||
|  | 	require SYSTEM . 'countries.conf.php'; | ||||||
|  |  | ||||||
|  | $nameOrNumberColumn = getAccountIdentityColumn(); | ||||||
|  |  | ||||||
|  | $hasSecretColumn = $db->hasColumn('accounts', 'secret'); | ||||||
|  | $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); | ||||||
|  | $hasTypeColumn = $db->hasColumn('accounts', 'type'); | ||||||
|  | $hasGroupColumn = $db->hasColumn('accounts', 'group_id'); | ||||||
|  |  | ||||||
|  | if (setting('core.account_country')) { | ||||||
|  | 	$countries = array(); | ||||||
|  | 	foreach (array('pl', 'se', 'br', 'us', 'gb') as $c) | ||||||
|  | 		$countries[$c] = $config['countries'][$c]; | ||||||
|  |  | ||||||
|  | 	$countries['--'] = '----------'; | ||||||
|  | 	foreach ($config['countries'] as $code => $c) | ||||||
|  | 		$countries[$code] = $c; | ||||||
|  | } | ||||||
|  | $web_acc = ACCOUNT_WEB_FLAGS; | ||||||
|  | $acc_type = setting('core.account_types'); | ||||||
|  | ?> | ||||||
|  |  | ||||||
|  | <link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ > | ||||||
|  | <script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script> | ||||||
|  |  | ||||||
|  | <?php | ||||||
|  | $id = 0; | ||||||
|  | $search_account = $search_account_email = ''; | ||||||
|  | if (isset($_REQUEST['id'])) | ||||||
|  | 	$id = (int)$_REQUEST['id']; | ||||||
|  | else if (isset($_REQUEST['search_email'])) { | ||||||
|  | 	$search_account_email = $_REQUEST['search_email']; | ||||||
|  | 	$accountModel = AccountModel::where('email', $search_account_email)->limit(11)->get(['email', 'id']); | ||||||
|  | 	if (count($accountModel) == 0) { | ||||||
|  | 		echo_error('No entries found.'); | ||||||
|  | 	} else if (count($accountModel) == 1) { | ||||||
|  | 		$id = $accountModel->first()->getKey(); | ||||||
|  | 	} else if (count($accountModel) > 10) { | ||||||
|  | 		echo_error('Specified e-mail resulted with too many accounts.'); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | else if (isset($_REQUEST['search'])) { | ||||||
|  | 	$search_account = $_REQUEST['search']; | ||||||
|  | 	$min_size = 3; | ||||||
|  | 	if (in_array($nameOrNumberColumn, ['id', 'number'])) { | ||||||
|  | 		$min_size = 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (strlen($search_account) < $min_size && !Validator::number($search_account)) { | ||||||
|  | 		echo_error('Account ' . $nameOrNumberColumn . ' is too short.'); | ||||||
|  | 	} else { | ||||||
|  | 		$query = AccountModel::where($nameOrNumberColumn, '=', $search_account)->limit(11)->get(['id', $nameOrNumberColumn]); | ||||||
|  | 		if (count($query) == 0) { | ||||||
|  | 			echo_error('No entries found.'); | ||||||
|  | 		} else if (count($query) == 1) { | ||||||
|  | 			$id = $query->first()->getKey(); | ||||||
|  | 		} else if (count($query) > 10) { | ||||||
|  | 			echo_error('Specified name resulted with too many accounts.'); | ||||||
|  | 		} else { | ||||||
|  | 			$str_construct = 'Do you mean?<ul class="mb-0">'; | ||||||
|  | 			foreach ($query as $row) { | ||||||
|  | 				$str_construct .= '<li><a href="' . $admin_base . '&id=' . $row->getKey() . '">' . $row->attributes[$nameOrNumberColumn] . '</a></li>'; | ||||||
|  | 			} | ||||||
|  | 			$str_construct .= '</ul>'; | ||||||
|  | 			echo_error($str_construct); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | ?> | ||||||
|  | <div class="row"> | ||||||
|  | 	<?php | ||||||
|  | 	$groups = new OTS_Groups_List(); | ||||||
|  | 	if ($id > 0) { | ||||||
|  | 		$account = new OTS_Account(); | ||||||
|  | 		$account->load($id); | ||||||
|  |  | ||||||
|  | 		if (isset($_POST['save']) && $account->isLoaded()) { | ||||||
|  | 			$error = false; | ||||||
|  |  | ||||||
|  | 			$_error = ''; | ||||||
|  | 			$account_db = new OTS_Account(); | ||||||
|  | 			if (USE_ACCOUNT_NAME) { | ||||||
|  | 				$name = $_POST['name']; | ||||||
|  |  | ||||||
|  | 				$account_db->find($name); | ||||||
|  | 				if ($account_db->isLoaded() && $account->getName() != $name) | ||||||
|  | 					echo_error('This name is already used. Please choose another name!'); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			$account_db->load($id); | ||||||
|  | 			if (!$account_db->isLoaded()) | ||||||
|  | 				echo_error('Account with this id doesn\'t exist.'); | ||||||
|  |  | ||||||
|  | 			//type/group | ||||||
|  | 			if ($hasTypeColumn || $hasGroupColumn) { | ||||||
|  | 				$group = $_POST['group']; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			$password = ((!empty($_POST["pass"]) ? $_POST['pass'] : null)); | ||||||
|  | 			if (!Validator::password($password)) { | ||||||
|  | 				$errors['password'] = Validator::getLastError(); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			//secret | ||||||
|  | 			if ($hasSecretColumn) { | ||||||
|  | 				$secret = $_POST['secret']; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			//key | ||||||
|  | 			$key = $_POST['key']; | ||||||
|  | 			$email = $_POST['email']; | ||||||
|  | 			if (!Validator::email($email)) | ||||||
|  | 				$errors['email'] = Validator::getLastError(); | ||||||
|  |  | ||||||
|  | 			// tibia coins | ||||||
|  | 			if (HAS_ACCOUNT_COINS) { | ||||||
|  | 				$t_coins = $_POST['t_coins']; | ||||||
|  | 				verify_number($t_coins, 'Tibia coins', 12); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// transferable tibia coins | ||||||
|  | 			if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) { | ||||||
|  | 				$t_coins_transferable = $_POST['t_coins_transferable']; | ||||||
|  | 				verify_number($t_coins_transferable, 'Transferable Tibia coins', 12); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// prem days | ||||||
|  | 			$p_days = (int)$_POST['p_days']; | ||||||
|  | 			verify_number($p_days, 'Prem days', 11); | ||||||
|  |  | ||||||
|  | 			//prem points | ||||||
|  | 			$p_points = $_POST['p_points']; | ||||||
|  | 			verify_number($p_points, 'Prem Points', 11); | ||||||
|  |  | ||||||
|  | 			//rl name | ||||||
|  | 			$rl_name = $_POST['rl_name']; | ||||||
|  |  | ||||||
|  | 			//location | ||||||
|  | 			$rl_loca = $_POST['rl_loca']; | ||||||
|  |  | ||||||
|  | 			//country | ||||||
|  | 			if(setting('core.account_country')) { | ||||||
|  | 				$rl_country = $_POST['rl_country']; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			$web_flags = $_POST['web_flags']; | ||||||
|  | 			verify_number($web_flags, 'Web Flags', 1); | ||||||
|  |  | ||||||
|  | 			//created | ||||||
|  | 			$created = strtotime($_POST['created']); | ||||||
|  | 			verify_number($created, 'Created', 11); | ||||||
|  |  | ||||||
|  | 			//web last login | ||||||
|  | 			$web_lastlogin = strtotime($_POST['web_lastlogin']); | ||||||
|  | 			verify_number($web_lastlogin, 'Web Last login', 11); | ||||||
|  |  | ||||||
|  | 			if (!$error && $hooks->trigger(HOOK_ADMIN_ACCOUNTS_SAVE_POST, ['account_id' => $account->getId(), 'account_email' =>  $account->getEMail()])) { | ||||||
|  | 				if (USE_ACCOUNT_NAME) { | ||||||
|  | 					$account->setName($name); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if ($hasTypeColumn) { | ||||||
|  | 					$account->setCustomField('type', $group); | ||||||
|  | 				} elseif ($hasGroupColumn) { | ||||||
|  | 					$account->setCustomField('group_id', $group); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if ($hasSecretColumn) { | ||||||
|  | 					$account->setCustomField('secret', $secret); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				$account->setCustomField('key', $key); | ||||||
|  | 				$account->setEMail($email); | ||||||
|  |  | ||||||
|  | 				if (HAS_ACCOUNT_COINS) { | ||||||
|  | 					$account->setCustomField('coins', $t_coins); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) { | ||||||
|  | 					$account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $t_coins_transferable); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				$lastDay = 0; | ||||||
|  | 				if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) { | ||||||
|  | 					$lastDay = time(); | ||||||
|  | 				} else if ($lastDay != 0) { | ||||||
|  | 					$lastDay = 0; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				$account->setPremDays($p_days); | ||||||
|  | 				$account->setLastLogin($lastDay); | ||||||
|  | 				if ($hasPointsColumn) { | ||||||
|  | 					$account->setCustomField('premium_points', $p_points); | ||||||
|  | 				} | ||||||
|  | 				$account->setRLName($rl_name); | ||||||
|  | 				$account->setLocation($rl_loca); | ||||||
|  |  | ||||||
|  | 				if(setting('core.account_country')) { | ||||||
|  | 					$account->setCountry($rl_country); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				$account->setCustomField('created', $created); | ||||||
|  | 				$account->setWebFlags($web_flags); | ||||||
|  | 				$account->setCustomField('web_lastlogin', $web_lastlogin); | ||||||
|  |  | ||||||
|  | 				if (isset($password)) { | ||||||
|  | 					if (USE_ACCOUNT_SALT) { | ||||||
|  | 						$salt = generateRandomString(10, false, true, true); | ||||||
|  | 						$password = $salt . $password; | ||||||
|  | 						$account->setCustomField('salt', $salt); | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					$password = encrypt($password); | ||||||
|  | 					$account->setPassword($password); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				$account->save(); | ||||||
|  | 				echo_success('Account saved at: ' . date('G:i')); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} else if ($id == 0) { | ||||||
|  | 		$accounts_db = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '`' . ($hasTypeColumn ? ',type' : ($hasGroupColumn ? ',group_id' : '')) . ', email FROM `accounts` ORDER BY `id` ASC'); | ||||||
|  | 		?> | ||||||
|  | 		<div class="col-12 col-sm-12 col-lg-10"> | ||||||
|  | 			<div class="card card-info card-outline"> | ||||||
|  | 				<div class="card-header"> | ||||||
|  | 					<h5 class="m-0">Accounts</h5> | ||||||
|  | 				</div> | ||||||
|  | 				<div class="card-body"> | ||||||
|  | 					<table class="acc_datatable table table-striped table-bordered table-responsive d-md-table"> | ||||||
|  | 						<thead> | ||||||
|  | 						<tr> | ||||||
|  | 							<th>ID</th> | ||||||
|  | 							<th><?= ($nameOrNumberColumn == 'name' ? 'Name' : 'Number'); ?></th> | ||||||
|  | 							<?php if($hasTypeColumn || $hasGroupColumn): ?> | ||||||
|  | 							<th>E-Mail</th> | ||||||
|  | 							<th>Position</th> | ||||||
|  | 							<?php endif; ?> | ||||||
|  | 							<th style="width: 40px">Edit</th> | ||||||
|  | 						</tr> | ||||||
|  | 						</thead> | ||||||
|  | 						<tbody> | ||||||
|  | 						<?php foreach ($accounts_db as $account_lst): ?> | ||||||
|  | 							<tr> | ||||||
|  | 								<th><?php echo $account_lst['id']; ?></th> | ||||||
|  | 								<td><?php echo $account_lst[$nameOrNumberColumn]; ?></a></td> | ||||||
|  | 								<td><?php echo $account_lst['email']; ?></td> | ||||||
|  | 								<?php if($hasTypeColumn || $hasGroupColumn): ?> | ||||||
|  | 								<td> | ||||||
|  | 									<?php if ($hasTypeColumn) { | ||||||
|  | 										echo $acc_type[$account_lst['type']]; | ||||||
|  | 									} elseif ($hasGroupColumn) { | ||||||
|  | 										$group = $groups->getGroups(); | ||||||
|  | 										echo $group[$account_lst['group_id']]; | ||||||
|  | 									} ?> | ||||||
|  | 								</td> | ||||||
|  | 								<?php endif; ?> | ||||||
|  | 								<td><a href="?p=accounts&id=<?php echo $account_lst['id']; ?>" class="btn btn-success btn-sm" title="Edit"> | ||||||
|  | 										<i class="fas fa-pencil-alt"></i> | ||||||
|  | 									</a> | ||||||
|  | 								</td> | ||||||
|  | 							</tr> | ||||||
|  | 						<?php endforeach; ?> | ||||||
|  | 						</tbody> | ||||||
|  | 					</table> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	<?php } ?> | ||||||
|  |  | ||||||
|  | 	<?php if (isset($account) && $account->isLoaded()) { ?> | ||||||
|  | 		<div class="col-12 col-sm-12 col-lg-10"> | ||||||
|  | 			<div class="card card-primary card-outline card-outline-tabs"> | ||||||
|  | 				<div class="card-header p-0 border-bottom-0"> | ||||||
|  | 					<ul class="nav nav-tabs" id="accounts-tab" role="tablist"> | ||||||
|  | 						<li class="nav-item"> | ||||||
|  | 							<a class="nav-link active" id="accounts-acc-tab" data-toggle="pill" href="#accounts-acc">Account</a> | ||||||
|  | 						</li> | ||||||
|  | 						<li class="nav-item"> | ||||||
|  | 							<a class="nav-link" id="accounts-logs-tab" data-toggle="pill" href="#accounts-logs">Logs</a> | ||||||
|  | 						</li> | ||||||
|  | 						<li class="nav-item"> | ||||||
|  | 							<a class="nav-link" id="accounts-chars-tab" data-toggle="pill" href="#accounts-chars">Characters</a> | ||||||
|  | 						</li> | ||||||
|  | 						<?php if ($db->hasTable('bans')) : ?> | ||||||
|  | 							<li class="nav-item"> | ||||||
|  | 								<a class="nav-link" id="accounts-bans-tab" data-toggle="pill" href="#accounts-bans">Bans</a> | ||||||
|  | 							</li> | ||||||
|  | 						<?php endif; | ||||||
|  |  | ||||||
|  | 						if ($db->hasTable('store_history') && $db->hasColumn('store_history', 'time')) : ?> | ||||||
|  | 							<li class="nav-item"> | ||||||
|  | 								<a class="nav-link" id="accounts-store-tab" data-toggle="pill" href="#accounts-store">Store History</a> | ||||||
|  | 							</li> | ||||||
|  | 						<?php endif; ?> | ||||||
|  | 					</ul> | ||||||
|  | 				</div> | ||||||
|  | 				<div class="card-body"> | ||||||
|  | 					<div class="tab-content" id="accounts-tabContent"> | ||||||
|  | 						<div class="tab-pane fade active show" id="accounts-acc"> | ||||||
|  | 							<form action="<?php echo $admin_base . ($id > 0 ? '&id=' . $id : ''); ?>" method="post"> | ||||||
|  | 								<?php csrf(); ?> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<?php if (USE_ACCOUNT_NAME): ?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-4"> | ||||||
|  | 											<label for="name">Account Name:</label> | ||||||
|  | 											<input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $account->getName(); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 									<?php elseif (USE_ACCOUNT_NUMBER): ?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-4"> | ||||||
|  | 											<label for="name">Account Number:</label> | ||||||
|  | 											<input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $account->getNumber(); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-5"> | ||||||
|  | 										<div class="form-check"> | ||||||
|  | 											<input type="checkbox" | ||||||
|  | 												   name="c_pass" | ||||||
|  | 												   id="c_pass" | ||||||
|  | 												   value="false" | ||||||
|  | 												   class="form-check-input"/> | ||||||
|  | 											<label for="c_pass">Password: (check to change)</label> | ||||||
|  | 										</div> | ||||||
|  | 										<div class="input-group"> | ||||||
|  | 											<input type="text" class="form-control" id="pass" name="pass" autocomplete="off" maxlength="20" value=""/> | ||||||
|  | 										</div> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-3"> | ||||||
|  | 										<label for="account_id" class="control-label">Account ID:</label> | ||||||
|  | 										<input type="text" class="form-control" id="account_id" name="account_id" autocomplete="off" size="8" maxlength="11" disabled value="<?php echo $account->getId(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<?php | ||||||
|  | 									$acc_group = $account->getAccGroupId(); | ||||||
|  | 									if ($hasTypeColumn) { | ||||||
|  | 										?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="group">Account Type:</label> | ||||||
|  | 											<select name="group" id="group" class="form-control"> | ||||||
|  | 												<?php foreach ($acc_type as $_id => $a_type): ?> | ||||||
|  | 													<option value="<?php echo($_id); ?>" <?php echo($acc_group == ($_id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option> | ||||||
|  | 												<?php endforeach; ?> | ||||||
|  | 											</select> | ||||||
|  | 										</div> | ||||||
|  | 										<?php | ||||||
|  | 									} elseif ($hasGroupColumn) { | ||||||
|  | 										?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="group">Account Type:</label> | ||||||
|  | 											<select name="group" id="group" class="form-control"> | ||||||
|  | 												<?php foreach ($groups->getGroups() as $_id => $group): ?> | ||||||
|  | 													<option value="<?php echo $_id; ?>" <?php echo($acc_group == $_id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option> | ||||||
|  | 												<?php endforeach; ?> | ||||||
|  | 											</select> | ||||||
|  | 										</div> | ||||||
|  | 									<?php } ?> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="web_flags">Website Access:</label> | ||||||
|  | 										<select name="web_flags" id="web_flags" class="form-control"> | ||||||
|  | 											<?php foreach ($web_acc as $_id => $a_type): ?> | ||||||
|  | 												<option value="<?php echo($_id); ?>" <?php echo($account->getWebFlags() == ($_id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option> | ||||||
|  | 											<?php endforeach; ?> | ||||||
|  | 										</select> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<?php if ($hasSecretColumn): ?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="secret">Secret:</label> | ||||||
|  | 											<input type="text" class="form-control" id="secret" name="secret" autocomplete="off" value="<?php echo $account->getCustomField('secret'); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="key">Recovery Key:</label> | ||||||
|  | 										<input type="text" class="form-control" id="key" name="key" autocomplete="off" value="<?php echo $account->getCustomField('key'); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="email">Email:</label><?php echo (setting('core.mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?> | ||||||
|  | 										<input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<?php if (HAS_ACCOUNT_COINS): ?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="t_coins">Tibia Coins:</label> | ||||||
|  | 											<input type="text" class="form-control" id="t_coins" name="t_coins" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField('coins') ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 									<?php if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS): ?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="t_coins_transferable">Transferable Tibia Coins:</label> | ||||||
|  | 											<input type="text" class="form-control" id="t_coins_transferable" name="t_coins_transferable" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN) ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="p_days">Premium Days:</label> | ||||||
|  | 										<input type="text" class="form-control" id="p_days" name="p_days" autocomplete="off" maxlength="11" value="<?php echo $account->getPremDays(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<?php if ($hasPointsColumn): ?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="p_points" class="control-label">Premium Points:</label> | ||||||
|  | 											<input type="text" class="form-control" id="p_points" name="p_points" autocomplete="off" maxlength="8" value="<?php echo $account->getCustomField('premium_points') ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-4"> | ||||||
|  | 										<label for="rl_name">RL Name:</label> | ||||||
|  | 										<input type="text" class="form-control" id="rl_name" name="rl_name" | ||||||
|  | 											   autocomplete="off" maxlength="20" | ||||||
|  | 											   value="<?php echo $account->getRLName(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-4"> | ||||||
|  | 										<label for="rl_loca">Location:</label> | ||||||
|  | 										<input type="text" class="form-control" id="rl_loca" name="rl_loca" | ||||||
|  | 											   autocomplete="off" maxlength="20" | ||||||
|  | 											   value="<?php echo $account->getLocation(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<?php if(setting('core.account_country')): ?> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-4"> | ||||||
|  | 										<label for="rl_country">Country:</label> | ||||||
|  | 										<select name="rl_country" id="rl_country" class="form-control"> | ||||||
|  | 											<?php foreach ($countries as $_id => $a_type): ?> | ||||||
|  | 												<option value="<?php echo($_id); ?>" <?php echo($account->getCountry() == ($_id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option> | ||||||
|  | 											<?php endforeach; ?> | ||||||
|  | 										</select> | ||||||
|  | 									</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="created" class="control-label">Created:</label> | ||||||
|  | 										<input type="text" class="form-control" id="created" name="created" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $account->getCustomField('created')); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="web_lastlogin" class="control-label">Web Last Login:</label> | ||||||
|  | 										<input type="text" class="form-control" id="web_lastlogin" name="web_lastlogin" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $account->getCustomField('web_lastlogin')); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  |  | ||||||
|  | 								<input type="hidden" name="save" value="yes"/> | ||||||
|  |  | ||||||
|  | 								<button type="submit" class="btn btn-info"><i class="fas fa-update"></i> Update</button> | ||||||
|  | 								<a href="<?php echo ADMIN_URL; ?>?p=accounts" class="btn btn-danger float-right"><i class="fas fa-cancel"></i> Cancel</a> | ||||||
|  | 							</form> | ||||||
|  | 						</div> | ||||||
|  | 						<div class="tab-pane fade" id="accounts-logs"> | ||||||
|  | 							<div class="row"> | ||||||
|  | 								<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||||
|  | 									<thead> | ||||||
|  | 										<tr> | ||||||
|  | 											<th>#</th> | ||||||
|  | 											<th>Date</th> | ||||||
|  | 											<th>Action</th> | ||||||
|  | 											<th>IP</th> | ||||||
|  | 										</tr> | ||||||
|  | 									</thead> | ||||||
|  | 									<tbody> | ||||||
|  | 										<?php | ||||||
|  | 											$accountActions = \MyAAC\Models\AccountAction::where('account_id', $account->getId())->orderByDesc('date')->get(); | ||||||
|  | 											foreach ($accountActions as $i => $log): | ||||||
|  | 												$log->ip = ($log->ip != 0 ? long2ip($log->ip) : inet_ntop($log->ipv6)); | ||||||
|  | 												?> | ||||||
|  | 											<tr> | ||||||
|  | 												<td><?php echo $i + 1; ?></td> | ||||||
|  | 												<td><?= date("M d Y, H:i:s", $log->date); ?></td> | ||||||
|  | 												<td><?= $log->action; ?></td> | ||||||
|  | 												<td><?= $log->ip; ?></td> | ||||||
|  | 											</tr> | ||||||
|  | 											<?php endforeach; ?> | ||||||
|  | 									</tbody> | ||||||
|  | 								</table> | ||||||
|  | 							</div> | ||||||
|  | 						</div> | ||||||
|  | 						<div class="tab-pane fade" id="accounts-chars"> | ||||||
|  | 							<div class="row"> | ||||||
|  | 								<?php | ||||||
|  | 								if (isset($account) && $account->isLoaded()) { | ||||||
|  | 									$account_players = Player::where('account_id', $account->getId())->orderBy('id')->get(); | ||||||
|  | 									if (isset($account_players)) { ?> | ||||||
|  | 										<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||||
|  | 											<thead> | ||||||
|  | 											<tr> | ||||||
|  | 												<th>#</th> | ||||||
|  | 												<th>Name</th> | ||||||
|  | 												<th>Level</th> | ||||||
|  | 												<th>Vocation</th> | ||||||
|  | 												<th style="width: 40px">Edit</th> | ||||||
|  | 											</tr> | ||||||
|  | 											</thead> | ||||||
|  | 											<tbody> | ||||||
|  | 											<?php foreach ($account_players as $i => $player): ?> | ||||||
|  | 												<tr> | ||||||
|  | 													<th><?php echo $i + 1; ?></th> | ||||||
|  | 													<td><?php echo $player->name; ?></td> | ||||||
|  | 													<td><?php echo $player->level; ?></td> | ||||||
|  | 													<td><?php echo $player->vocation_name; ?></td> | ||||||
|  | 													<td><a href="?p=players&id=<?php echo $player->getKey() ?>" class=" btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></a></td> | ||||||
|  | 												</tr> | ||||||
|  | 											<?php endforeach ?> | ||||||
|  | 											</tbody> | ||||||
|  | 										</table> | ||||||
|  | 										<?php | ||||||
|  | 									} | ||||||
|  | 								} ?> | ||||||
|  | 							</div> | ||||||
|  | 						</div> | ||||||
|  | 						<?php if ($db->hasTable('bans')) : ?> | ||||||
|  | 							<div class="tab-pane fade" id="accounts-bans"> | ||||||
|  | 								<?php | ||||||
|  | 								$bans = $db->query('SELECT * FROM ' . $db->tableName('bans') . ' WHERE ' . $db->fieldName('active') . ' = 1 AND ' . $db->fieldName('id') . ' = ' . $account->getId() . ' ORDER BY ' . $db->fieldName('added') . ' DESC LIMIT 10'); | ||||||
|  | 								if ($bans->rowCount()) { | ||||||
|  | 									?> | ||||||
|  | 									<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||||
|  | 										<thead> | ||||||
|  | 										<tr> | ||||||
|  | 											<th>Nick</th> | ||||||
|  | 											<th>Type</th> | ||||||
|  | 											<th>Expires</th> | ||||||
|  | 											<th>Reason</th> | ||||||
|  | 											<th>Comment</th> | ||||||
|  | 											<th>Added by:</th> | ||||||
|  | 										</tr> | ||||||
|  | 										</thead> | ||||||
|  | 										<tbody> | ||||||
|  | 										<?php | ||||||
|  | 										foreach ($bans as $ban) { | ||||||
|  | 											?> | ||||||
|  | 											<tr> | ||||||
|  | 												<td><?php | ||||||
|  | 													$pName = getPlayerNameByAccount($ban['value']); | ||||||
|  | 													echo '<a href="?p=players&search=' . $pName . '">' . $pName . '</a>'; ?> | ||||||
|  | 												</td> | ||||||
|  | 												<td><?php echo getBanType($ban['type']); ?></td> | ||||||
|  | 												<td> | ||||||
|  | 													<?php | ||||||
|  | 													if ($ban['expires'] == "-1") | ||||||
|  | 														echo 'Never'; | ||||||
|  | 													else | ||||||
|  | 														echo date("H:i:s", $ban['expires']) . '<br/>' . date("d M Y", $ban['expires']); | ||||||
|  | 													?> | ||||||
|  | 												</td> | ||||||
|  | 												<td><?php echo getBanReason($ban['reason']); ?></td> | ||||||
|  | 												<td><?php echo $ban['comment']; ?></td> | ||||||
|  | 												<td> | ||||||
|  | 													<?php | ||||||
|  | 													if ($ban['admin_id'] == "0") | ||||||
|  | 														echo 'Autoban'; | ||||||
|  | 													else | ||||||
|  | 														$aName = getPlayerNameByAccount($ban['admin_id']); | ||||||
|  | 													echo '<a href="?p=players&search=' . $aName . '">' . $aName . '</a>'; | ||||||
|  | 													echo '<br/>' . date("d.m.Y", $ban['added']); | ||||||
|  | 													?> | ||||||
|  | 												</td> | ||||||
|  | 											</tr> | ||||||
|  | 										<?php } ?> | ||||||
|  | 										</tbody> | ||||||
|  | 									</table> | ||||||
|  | 									<?php | ||||||
|  | 								} else { | ||||||
|  | 									echo 'No Account bans.'; | ||||||
|  | 								} ?> | ||||||
|  | 							</div> | ||||||
|  | 						<?php endif; | ||||||
|  | 						if ($db->hasTable('store_history') && $db->hasColumn('store_history', 'time')) { ?> | ||||||
|  | 							<div class="tab-pane fade" id="accounts-store"> | ||||||
|  | 								<?php $store_history = $db->query('SELECT * FROM `store_history` WHERE `account_id` = "' . $account->getId() . '" ORDER BY `time` DESC')->fetchAll(); ?> | ||||||
|  | 								<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||||
|  | 									<thead> | ||||||
|  | 									<tr> | ||||||
|  | 										<th>Description</th> | ||||||
|  | 										<th>Coins</th> | ||||||
|  | 										<th>Date</th> | ||||||
|  | 									</tr> | ||||||
|  | 									</thead> | ||||||
|  | 									<tbody> | ||||||
|  | 									<?php foreach ($store_history as $p): ?> | ||||||
|  | 										<tr> | ||||||
|  | 											<td><?php echo $p['description']; ?></td> | ||||||
|  | 											<td><?php echo $p['coin_amount']; ?></td> | ||||||
|  | 											<td><?php echo date('d M y H:i:s', $p['time']); ?></td> | ||||||
|  | 										</tr> | ||||||
|  | 									<?php endforeach; ?> | ||||||
|  | 									</tbody> | ||||||
|  | 								</table> | ||||||
|  | 							</div> | ||||||
|  | 						<?php } ?> | ||||||
|  | 					</div> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	<?php } ?> | ||||||
|  | 	<div class="col-12 col-sm-12 col-lg-2"> | ||||||
|  | 		<div class="card card-info card-outline"> | ||||||
|  | 			<div class="card-header"> | ||||||
|  | 				<h5 class="m-0">Search Accounts</h5> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="card-body"> | ||||||
|  | 				<div class="row"> | ||||||
|  | 					<div class="col-6 col-lg-12"> | ||||||
|  | 						<form action="<?php echo $admin_base; ?>" method="post"> | ||||||
|  | 							<?php csrf(); ?> | ||||||
|  | 							<label for="search">Account E-Mail:</label> | ||||||
|  | 							<div class="input-group input-group-sm"> | ||||||
|  | 								<input type="email" class="form-control" id="search_email" name="search_email" value="<?= escapeHtml($search_account_email); ?>" maxlength="255" size="255"> | ||||||
|  | 								<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span> | ||||||
|  | 							</div> | ||||||
|  | 						</form> | ||||||
|  | 					</div> | ||||||
|  | 					<div class="col-6 col-lg-12"> | ||||||
|  | 						<form action="<?php echo $admin_base; ?>" method="post"> | ||||||
|  | 							<?php csrf(); ?> | ||||||
|  | 							<label for="search">Account Name:</label> | ||||||
|  | 							<div class="input-group input-group-sm"> | ||||||
|  | 								<input type="text" class="form-control" id="search" name="search" value="<?= escapeHtml($search_account); ?>" maxlength="32" size="32"> | ||||||
|  | 								<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span> | ||||||
|  | 							</div> | ||||||
|  | 						</form> | ||||||
|  | 					</div> | ||||||
|  | 					<div class="col-6 col-lg-12"> | ||||||
|  | 						<form action="<?php echo $admin_base; ?>" method="post"> | ||||||
|  | 							<?php csrf(); ?> | ||||||
|  | 							<label for="id">Account ID:</label> | ||||||
|  | 							<div class="input-group input-group-sm"> | ||||||
|  | 								<input type="text" class="form-control" id="id" name="id" value="<?= $id; ?>" maxlength="32" size="32"> | ||||||
|  | 								<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span> | ||||||
|  | 							</div> | ||||||
|  | 						</form> | ||||||
|  | 					</div> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  | <script> | ||||||
|  | 	$(document).ready(function () { | ||||||
|  | 		$('#created').datetimepicker({format: "M d Y, H:i:s",}); | ||||||
|  | 		$('#web_lastlogin').datetimepicker({format: 'M d Y, H:i:s'}); | ||||||
|  |  | ||||||
|  | 		$('#c_pass').change(function () { | ||||||
|  | 			const ipass = $('input[name=pass]'); | ||||||
|  | 			ipass[0].disabled = !this.checked; | ||||||
|  | 			ipass[0].value = ''; | ||||||
|  | 		}).change(); | ||||||
|  |  | ||||||
|  | 		$('.acc_datatable').DataTable({ | ||||||
|  | 			"order": [[0, "asc"]] | ||||||
|  | 		}); | ||||||
|  | 	}); | ||||||
|  | </script> | ||||||
							
								
								
									
										131
									
								
								admin/pages/changelog.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,131 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * CHANGELOG modifier | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @author    Lee | ||||||
|  |  * @copyright 2020 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Changelog; | ||||||
|  | use MyAAC\Models\Changelog as ModelsChangelog; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $title = 'Changelog'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) { | ||||||
|  | 	echo 'Access denied.'; | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $use_datatable = true; | ||||||
|  | const CL_LIMIT = 600; // maximum changelog body length | ||||||
|  |  | ||||||
|  | $id = $_GET['id'] ?? 0; | ||||||
|  |  | ||||||
|  | if(!empty($action) && isRequestMethod('post')) | ||||||
|  | { | ||||||
|  | 	$id = $_POST['id'] ?? null; | ||||||
|  | 	$body = isset($_POST['body']) ? stripslashes($_POST['body']) : null; | ||||||
|  | 	$create_date = isset($_POST['createdate']) ? (int)strtotime($_POST['createdate'] ): null; | ||||||
|  | 	$player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : null; | ||||||
|  | 	$type = isset($_POST['type']) ? (int)$_POST['type'] : null; | ||||||
|  | 	$where = isset($_POST['where']) ? (int)$_POST['where'] : null; | ||||||
|  |  | ||||||
|  | 	$errors = array(); | ||||||
|  |  | ||||||
|  | 	if($action == 'new') { | ||||||
|  |  | ||||||
|  | 		if(isset($body) && Changelog::add($body, $type, $where, $player_id, $create_date, $errors)) { | ||||||
|  | 			$body = ''; | ||||||
|  | 			$type = $where = $player_id = $create_date = 0; | ||||||
|  |  | ||||||
|  | 			success('Added successful.'); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else if($action == 'delete') { | ||||||
|  | 		if (Changelog::delete($id, $errors)) { | ||||||
|  | 			success('Deleted successful.'); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else if($action == 'edit') | ||||||
|  | 	{ | ||||||
|  | 		if(isset($id) && !isset($body)) { | ||||||
|  | 			$cl = Changelog::get($id); | ||||||
|  | 			$body = $cl['body']; | ||||||
|  | 			$type = $cl['type']; | ||||||
|  | 			$where = $cl['where']; | ||||||
|  | 			$create_date = $cl['date']; | ||||||
|  | 			$player_id = $cl['player_id']; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			if(Changelog::update($id, $body, $type, $where, $player_id, $create_date,$errors)) { | ||||||
|  | 				$action = $body = ''; | ||||||
|  | 				$type = $where = $player_id = $create_date = 0; | ||||||
|  |  | ||||||
|  | 				success('Updated successful.'); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else if($action == 'hide') { | ||||||
|  | 		if (Changelog::toggleHide($id, $errors, $status)) { | ||||||
|  | 			success(($status == 1 ? 'Hide' : 'Show') . ' successful.'); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if(!empty($errors)) | ||||||
|  | 		error(implode(", ", $errors)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $changelogs = ModelsChangelog::orderBy('id')->get()->toArray(); | ||||||
|  |  | ||||||
|  | $i = 0; | ||||||
|  |  | ||||||
|  | $log_type = [ | ||||||
|  | 	['id' => 1, 'icon' => 'added'], | ||||||
|  | 	['id' => 2, 'icon' => 'removed'], | ||||||
|  | 	['id' => 3, 'icon' => 'changed'], | ||||||
|  | 	['id' => 4, 'icon' => 'fixed'], | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | $log_where = [ | ||||||
|  | 	['id' => 1, 'icon' => 'server'], | ||||||
|  | 	['id' => 2, 'icon' => 'website'], | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | foreach($changelogs as $key => &$log) | ||||||
|  | { | ||||||
|  | 	$log['type'] = getChangelogType($log['type']); | ||||||
|  | 	$log['where'] = getChangelogWhere($log['where']); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if($action == 'edit' || $action == 'new') { | ||||||
|  | 	if($action == 'edit') { | ||||||
|  | 		$player = new OTS_Player(); | ||||||
|  | 		$player->load($player_id); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$account_players = $account_logged->getPlayersList(); | ||||||
|  | 	$account_players->orderBy('group_id', POT::ORDER_DESC); | ||||||
|  | 	$twig->display('admin.changelog.form.html.twig', array( | ||||||
|  | 		'action' => $action, | ||||||
|  | 		'cl_link_form' => constant('ADMIN_URL').'?p=changelog', | ||||||
|  | 		'cl_id' => $id ?? null, | ||||||
|  | 		'body' => isset($body) ? escapeHtml($body) : '', | ||||||
|  | 		'create_date' => $create_date ?? '', | ||||||
|  | 		'player_id' => $player_id ?? null, | ||||||
|  | 		'account_players' => $account_players, | ||||||
|  | 		'type' => $type ?? 0, | ||||||
|  | 		'where' => $where ?? 0, | ||||||
|  | 		'log_type' => $log_type, | ||||||
|  | 		'log_where' => $log_where, | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  | $twig->display('admin.changelog.html.twig', array( | ||||||
|  | 	'changelogs' => $changelogs, | ||||||
|  | )); | ||||||
							
								
								
									
										25
									
								
								admin/pages/clmd.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,25 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * CHANGELOG viewer | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @author    Lee | ||||||
|  |  * @copyright 2020 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'MyAAC Changelog'; | ||||||
|  |  | ||||||
|  | if (!file_exists(BASE . 'CHANGELOG-1.x.md')) { | ||||||
|  | 	echo 'File CHANGELOG.md doesn\'t exist.'; | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $changelog = file_get_contents(BASE . 'CHANGELOG-1.x.md'); | ||||||
|  |  | ||||||
|  | $Parsedown = new Parsedown(); | ||||||
|  |  | ||||||
|  | $changelog = $Parsedown->text($changelog); # prints: <p>Hello <em>Parsedown</em>!</p> | ||||||
|  |  | ||||||
|  | echo '<div>' . $changelog . '</div>'; | ||||||
							
								
								
									
										63
									
								
								admin/pages/dashboard.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,63 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Dashboard | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Dashboard'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | if (isset($_POST['clear_cache'])) { | ||||||
|  | 	if (clearCache()) { | ||||||
|  | 		success('Cache cleared.'); | ||||||
|  | 	} else { | ||||||
|  | 		error('Error while clearing cache.'); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (isset($_POST['maintenance'])) { | ||||||
|  | 	$message = (!empty($_POST['message']) ? $_POST['message'] : null); | ||||||
|  | 	$_status = (isset($_POST['status']) && $_POST['status'] == 'true'); | ||||||
|  | 	$_status = ($_status ? '0' : '1'); | ||||||
|  |  | ||||||
|  | 	if (empty($message)) { | ||||||
|  | 		error('Message cannot be empty.'); | ||||||
|  | 	} else if (strlen($message) > 255) { | ||||||
|  | 		error('Message is too long. Maximum length allowed is 255 chars.'); | ||||||
|  | 	} else { | ||||||
|  | 		$tmp = ''; | ||||||
|  | 		if (fetchDatabaseConfig('site_closed', $tmp)) | ||||||
|  | 			updateDatabaseConfig('site_closed', $_status); | ||||||
|  | 		else | ||||||
|  | 			registerDatabaseConfig('site_closed', $_status); | ||||||
|  |  | ||||||
|  | 		if (fetchDatabaseConfig('site_closed_message', $tmp)) | ||||||
|  | 			updateDatabaseConfig('site_closed_message', $message); | ||||||
|  | 		else | ||||||
|  | 			registerDatabaseConfig('site_closed_message', $message); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | $is_closed = getDatabaseConfig('site_closed') == '1'; | ||||||
|  |  | ||||||
|  | $closed_message = 'Server is under maintenance, please visit later.'; | ||||||
|  | $tmp = ''; | ||||||
|  | if (fetchDatabaseConfig('site_closed_message', $tmp)) | ||||||
|  | 	$closed_message = $tmp; | ||||||
|  |  | ||||||
|  | $settingAdminPanelModules = setting('core.admin_panel_modules'); | ||||||
|  | if (count($settingAdminPanelModules) > 0) { | ||||||
|  | 	echo '<div class="row">'; | ||||||
|  | 	$twig_loader->prependPath(__DIR__ . '/modules/templates'); | ||||||
|  | 	foreach ($settingAdminPanelModules as $box) { | ||||||
|  | 		$file = __DIR__ . '/modules/' . $box . '.php'; | ||||||
|  | 		if (file_exists($file)) { | ||||||
|  | 			include($file); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | echo '</div>'; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								admin/pages/data.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,13 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Load items.xml | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Server Data'; | ||||||
|  |  | ||||||
|  | $twig->display('admin.data.html.twig'); | ||||||
							
								
								
									
										0
									
								
								admin/pages/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										26
									
								
								admin/pages/login.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,26 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Login | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Login'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | require PAGES . 'account/login.php'; | ||||||
|  | if ($logged) { | ||||||
|  | 	header('Location: ' . (admin() ? ADMIN_URL : BASE_URL)); | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('admin.login.html.twig', [ | ||||||
|  | 	'logout' => (ACTION == 'logout' ? 'You have  been logged out!'  : ''), | ||||||
|  | 	'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number', | ||||||
|  | 	'account_login_by' => getAccountLoginByLabel(), | ||||||
|  | 	'errors' => $errors ?? '' | ||||||
|  | ]); | ||||||
							
								
								
									
										83
									
								
								admin/pages/logs.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,83 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Logs | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2020 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Logs Viewer'; | ||||||
|  | $use_datatable = true; | ||||||
|  |  | ||||||
|  | $files = array(); | ||||||
|  | $aac_path_logs = BASE . 'system/logs/'; | ||||||
|  | foreach (scandir($aac_path_logs, SCANDIR_SORT_ASCENDING) as $f) { | ||||||
|  | 	if ($f[0] === '.' || is_dir($aac_path_logs . $f) || $f === 'index.html') { | ||||||
|  | 		continue; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$files[] = array($f, $aac_path_logs); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $server_path_logs = $config['server_path'] . 'logs/'; | ||||||
|  | if (!file_exists($server_path_logs)) { | ||||||
|  | 	$server_path_logs = $config['data_path'] . 'logs/'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (file_exists($server_path_logs)) { | ||||||
|  | 	foreach (scandir($server_path_logs, SCANDIR_SORT_ASCENDING) as $f) { | ||||||
|  | 		if ($f[0] === '.') { | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (is_dir($server_path_logs . $f)) { | ||||||
|  | 			foreach (scandir($server_path_logs . $f, SCANDIR_SORT_ASCENDING) as $f2) { | ||||||
|  | 				if ($f2[0] === '.') { | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				$files[] = array($f . '/' . $f2, $server_path_logs); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		$files[] = array($f, $server_path_logs); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | foreach ($files as &$f) { | ||||||
|  | 	$f['mtime'] = filemtime($f[1] . $f[0]); | ||||||
|  | 	$f['name'] = $f[0]; | ||||||
|  | } | ||||||
|  | unset($f); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | define('EXIST_NONE', 0); | ||||||
|  | define('EXIST_SERVER_LOG', 1); | ||||||
|  | define('EXIST_AAC_LOG', 2); | ||||||
|  |  | ||||||
|  | $exist = EXIST_NONE; | ||||||
|  | $file = isset($_GET['file']) ? $_GET['file'] : null; | ||||||
|  | if (!empty($file)) { | ||||||
|  | 	if (!preg_match('/[^A-z0-9\' _\/\-\.]/', $file)) { | ||||||
|  | 		if (file_exists($aac_path_logs . $file)) { | ||||||
|  | 			$exist = EXIST_AAC_LOG; | ||||||
|  | 		} else if (file_exists($server_path_logs . $file)) { | ||||||
|  | 			$exist = EXIST_SERVER_LOG; | ||||||
|  | 		} else { | ||||||
|  | 			echo 'Specified file does not exist.'; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ($exist !== EXIST_NONE) { | ||||||
|  | 			$file_content = nl2br(file_get_contents(($exist === EXIST_SERVER_LOG ? $server_path_logs : $aac_path_logs) . $file)); | ||||||
|  | 			$twig->display('admin.logs.view.html.twig', array('file' => $file, 'content' => $file_content)); | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		echo 'Invalid file name specified.'; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('admin.logs.html.twig', array('files' => $files)); | ||||||
							
								
								
									
										90
									
								
								admin/pages/mailer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,90 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Mailer | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Account; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Mailer'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | if (!hasFlag(FLAG_CONTENT_MAILER) && !superAdmin()) { | ||||||
|  | 	echo 'Access denied.'; | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (!setting('core.mail_enabled')) { | ||||||
|  | 	echo 'Mail support disabled in config.'; | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null; | ||||||
|  | $mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null; | ||||||
|  | $mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null; | ||||||
|  | $mail_verified_only = $_POST['mail_verified_only'] ?? false; | ||||||
|  |  | ||||||
|  | if (isset($_POST['submit'])) { | ||||||
|  | 	if (empty($mail_subject)) { | ||||||
|  | 		warning('Please enter subject of the message.'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (empty($mail_content)) { | ||||||
|  | 		warning('Please enter content of the message.'); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | if (!empty($mail_to)) { | ||||||
|  | 	if(!Validator::email($mail_to)) { | ||||||
|  | 		warning('E-Mail is invalid.'); | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		if (!empty($mail_content) && !empty($mail_subject)) { | ||||||
|  | 			if (_mail($mail_to, $mail_subject, $mail_content)) { | ||||||
|  | 				success("Successfully mailed <strong>$mail_to</strong>"); | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				error("Error while sending mail to <strong>$mail_to</strong>. More info can be found in system/logs/mailer-error.log"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) { | ||||||
|  | 	$success = 0; | ||||||
|  | 	$failed = 0; | ||||||
|  |  | ||||||
|  | 	$query = Account::where('email', '!=', ''); | ||||||
|  |  | ||||||
|  | 	if ($mail_verified_only) { | ||||||
|  | 		info('Note: Sending only to users with verified E-Mail.'); | ||||||
|  | 		$query->where('email_verified', 1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	foreach ($query->get(['email']) as $email) { | ||||||
|  | 		if (_mail($email->email, $mail_subject, $mail_content)) { | ||||||
|  | 			$success++; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			$failed++; | ||||||
|  | 			echo '<br />'; | ||||||
|  | 			error('An error occorred while sending email to <b>' . $email->email . '</b>. For Admin: More info can be found in system/logs/mailer-error.log'); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	success('Mailing finished.'); | ||||||
|  | 	success("$success emails delivered."); | ||||||
|  | 	warning("$failed emails failed."); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('admin.mailer.html.twig', [ | ||||||
|  | 	'mail_to' => $mail_to, | ||||||
|  | 	'mail_subject' => $mail_subject, | ||||||
|  | 	'mail_content' => $mail_content, | ||||||
|  | 	'mail_verified_only' => $mail_verified_only, | ||||||
|  | ]); | ||||||
							
								
								
									
										183
									
								
								admin/pages/mass_account.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,183 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Account Admin Tool | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @author    Lee | ||||||
|  |  * @copyright 2020 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Account; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $title = 'Mass Account Actions'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); | ||||||
|  | $freePremium = $config['lua']['freePremium']; | ||||||
|  |  | ||||||
|  | function admin_give_points($points) | ||||||
|  | { | ||||||
|  | 	global $hasPointsColumn; | ||||||
|  |  | ||||||
|  | 	if (!$hasPointsColumn) { | ||||||
|  | 		displayMessage('Points not supported.'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!Account::query()->increment('premium_points', $points)) { | ||||||
|  | 		displayMessage('Failed to add points.'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	displayMessage($points . ' points added to all accounts.', true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function admin_give_coins($coins) | ||||||
|  | { | ||||||
|  | 	if (!HAS_ACCOUNT_COINS) { | ||||||
|  | 		displayMessage('Coins not supported.'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!Account::query()->increment('coins', $coins)) { | ||||||
|  | 		displayMessage('Failed to add coins.'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	displayMessage($coins . ' coins added to all accounts.', true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function admin_give_premdays($days) | ||||||
|  | { | ||||||
|  | 	global $db, $freePremium; | ||||||
|  |  | ||||||
|  | 	if ($freePremium) { | ||||||
|  | 		displayMessage('Premium days not supported. Free Premium enabled.'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$value = $days * 86400; | ||||||
|  | 	$now = time(); | ||||||
|  | 	// othire | ||||||
|  | 	if ($db->hasColumn('accounts', 'premend')) { | ||||||
|  | 		// append premend | ||||||
|  | 		if (Account::where('premend', '>', $now)->increment('premend', $value)) { | ||||||
|  | 			// set premend | ||||||
|  | 			if (Account::where('premend', '<=', $now)->update(['premend' => $now + $value])) { | ||||||
|  | 				displayMessage($days . ' premium days added to all accounts.', true); | ||||||
|  | 				return; | ||||||
|  | 			} else { | ||||||
|  | 				displayMessage('Failed to execute set query.'); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			displayMessage('Failed to execute append query.'); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// tfs 0.x | ||||||
|  | 	if ($db->hasColumn('accounts', 'premdays')) { | ||||||
|  | 		// append premdays | ||||||
|  | 		if (Account::query()->update(['premdays' => $days])) { | ||||||
|  | 			// append lastday | ||||||
|  | 			if (Account::where('lastday', '>', $now)->increment('lastday', $value)) { | ||||||
|  | 				// set lastday | ||||||
|  | 				if (Account::where('lastday', '<=', $now)->update(['lastday' => $now + $value])) { | ||||||
|  | 					displayMessage($days . ' premium days added to all accounts.', true); | ||||||
|  | 					return; | ||||||
|  | 				} else { | ||||||
|  | 					displayMessage('Failed to execute set query.'); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				return; | ||||||
|  | 			} else { | ||||||
|  | 				displayMessage('Failed to execute append query.'); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			displayMessage('Failed to execute set days query.'); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// tfs 1.x | ||||||
|  | 	if ($db->hasColumn('accounts', 'premium_ends_at')) { | ||||||
|  | 		// append premium_ends_at | ||||||
|  | 		if (Account::where('premium_ends_at', '>', $now)->increment('premium_ends_at', $value)) { | ||||||
|  | 			// set premium_ends_at | ||||||
|  | 			if (Account::where('premium_ends_at', '<=', $now)->update(['premium_ends_at' => $now + $value])) { | ||||||
|  | 				displayMessage($days . ' premium days added to all accounts.', true); | ||||||
|  | 				return; | ||||||
|  | 			} else { | ||||||
|  | 				displayMessage('Failed to execute set query.'); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			displayMessage('Failed to execute append query.'); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	displayMessage('Premium Days not supported.'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (!empty(ACTION) && isRequestMethod('post')) { | ||||||
|  |  | ||||||
|  | 	$action = ACTION; | ||||||
|  |  | ||||||
|  | 	if (preg_match("/[^A-z0-9_\-]/", $action)) { | ||||||
|  | 		displayMessage('Invalid action.'); | ||||||
|  | 	} else { | ||||||
|  | 		$value = isset($_POST['value']) ? intval($_POST['value']) : 0; | ||||||
|  |  | ||||||
|  | 		if (!$value) { | ||||||
|  | 			displayMessage('Please fill all inputs'); | ||||||
|  | 		} else { | ||||||
|  | 			switch ($action) { | ||||||
|  | 				case 'give-points': | ||||||
|  | 					admin_give_points($value); | ||||||
|  | 					break; | ||||||
|  | 				case 'give-coins': | ||||||
|  | 					admin_give_coins($value); | ||||||
|  | 					break; | ||||||
|  | 				case 'give-premdays': | ||||||
|  | 					admin_give_premdays($value); | ||||||
|  | 					break; | ||||||
|  | 				default: | ||||||
|  | 					displayMessage('Action ' . $action . 'not found.'); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | else { | ||||||
|  | 	$twig->display('admin.tools.account.html.twig', array( | ||||||
|  | 		'hasCoinsColumn' => HAS_ACCOUNT_COINS, | ||||||
|  | 		'hasPointsColumn' => $hasPointsColumn, | ||||||
|  | 		'freePremium' => $freePremium, | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function displayMessage($message, $success = false) { | ||||||
|  | 	global $twig, $hasPointsColumn, $freePremium; | ||||||
|  |  | ||||||
|  | 	$success ? success($message): error($message); | ||||||
|  |  | ||||||
|  | 	$twig->display('admin.tools.account.html.twig', array( | ||||||
|  | 		'hasCoinsColumn' => HAS_ACCOUNT_COINS, | ||||||
|  | 		'hasPointsColumn' => $hasPointsColumn, | ||||||
|  | 		'freePremium' => $freePremium, | ||||||
|  | 	)); | ||||||
|  | } | ||||||
							
								
								
									
										107
									
								
								admin/pages/mass_teleport.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,107 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Teleport Admin Tool | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @author    Lee | ||||||
|  |  * @copyright 2020 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Player; | ||||||
|  | use MyAAC\Models\PlayerOnline; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $title = 'Mass Teleport Actions'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | function admin_teleport_position($x, $y, $z) { | ||||||
|  | 	if (!Player::query()->update([ | ||||||
|  | 		'posx' => $x, 'posy' => $y, 'posz' => $z | ||||||
|  | 	])) { | ||||||
|  | 		displayMessage('Failed to execute query. Probably already updated.'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	displayMessage('Player\'s position updated.', true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function admin_teleport_town($town_id) { | ||||||
|  | 	if (!Player::query()->update([ | ||||||
|  | 		'town_id' => $town_id, | ||||||
|  | 	])) { | ||||||
|  | 		displayMessage('Failed to execute query. Probably already updated.'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	displayMessage('Player\'s town updated.', true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (!empty(ACTION) && isRequestMethod('post'))    { | ||||||
|  |  | ||||||
|  | 	$action = ACTION; | ||||||
|  |  | ||||||
|  | 	if (preg_match("/[^A-z0-9_\-]/", $action)) { | ||||||
|  | 		displayMessage('Invalid action.'); | ||||||
|  | 	} else { | ||||||
|  |  | ||||||
|  | 		$playersOnline = 0; | ||||||
|  | 		if($db->hasTable('players_online')) {// tfs 1.0 | ||||||
|  | 			$playersOnline = PlayerOnline::count(); | ||||||
|  | 		} else { | ||||||
|  | 			$playersOnline = Player::online()->count(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ($playersOnline > 0) { | ||||||
|  | 			displayMessage('Please, close the server before execute this action otherwise players will not be affected.'); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		$town_id = isset($_POST['town_id']) ? intval($_POST['town_id']) : null; | ||||||
|  | 		$posx = isset($_POST['posx']) ? intval($_POST['posx']) : null; | ||||||
|  | 		$posy = isset($_POST['posy']) ? intval($_POST['posy']) : null; | ||||||
|  | 		$posz = isset($_POST['posz']) ? intval($_POST['posz']) : null; | ||||||
|  | 		$to_temple = $_POST['to_temple'] ?? null; | ||||||
|  |  | ||||||
|  | 		switch ($action) { | ||||||
|  | 			case 'set-town': | ||||||
|  | 				if (!$town_id) { | ||||||
|  | 					displayMessage('Please fill all inputs'); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if (!isset($config['towns'][$town_id])) { | ||||||
|  | 					displayMessage('Specified town does not exist'); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				admin_teleport_town($town_id); | ||||||
|  | 				break; | ||||||
|  | 			case 'set-position': | ||||||
|  | 				if (!$to_temple &&  ($posx < 0 || $posx > 65535 || $posy < 0 || $posy > 65535|| $posz < 0 || $posz > 16)) { | ||||||
|  | 					displayMessage('Invalid Position'); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				admin_teleport_position($posx, $posy, $posz); | ||||||
|  | 				break; | ||||||
|  | 			default: | ||||||
|  | 				displayMessage('Action ' . $action . 'not found.'); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
|  | else { | ||||||
|  | 	$twig->display('admin.tools.teleport.html.twig', array()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | function displayMessage($message, $success = false) { | ||||||
|  | 	global $twig; | ||||||
|  |  | ||||||
|  | 	$success ? success($message): error($message); | ||||||
|  | 	$twig->display('admin.tools.teleport.html.twig', array()); | ||||||
|  | } | ||||||
							
								
								
									
										210
									
								
								admin/pages/menus.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,210 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Menus | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Cache\Cache; | ||||||
|  | use MyAAC\Models\Menu; | ||||||
|  | use MyAAC\Plugins; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Menus'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | if (!hasFlag(FLAG_CONTENT_MENUS) && !superAdmin()) { | ||||||
|  | 	echo 'Access denied.'; | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $pluginThemes = Plugins::getThemes(); | ||||||
|  |  | ||||||
|  | if (isset($_POST['template'])) { | ||||||
|  | 	$template = $_POST['template']; | ||||||
|  |  | ||||||
|  | 	if (isset($_POST['save'])) { | ||||||
|  | 		$post_menu = $_POST['menu'] ?? []; | ||||||
|  | 		$post_menu_link = $_POST['menu_link'] ?? []; | ||||||
|  | 		$post_menu_blank = $_POST['menu_blank'] ?? []; | ||||||
|  | 		$post_menu_color = $_POST['menu_color'] ?? []; | ||||||
|  | 		if (count($post_menu) != count($post_menu_link)) { | ||||||
|  | 			echo 'Menu count is not equal menu links. Something went wrong when sending form.'; | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		Menu::where('template', $template)->delete(); | ||||||
|  | 		foreach ($post_menu as $category => $menus) { | ||||||
|  | 			foreach ($menus as $i => $menu) { | ||||||
|  | 				if (empty($menu)) // don't save empty menu item | ||||||
|  | 					continue; | ||||||
|  |  | ||||||
|  | 				try { | ||||||
|  | 					Menu::create([ | ||||||
|  | 						'template' => $template, | ||||||
|  | 						'name' => $menu, | ||||||
|  | 						'link' => $post_menu_link[$category][$i], | ||||||
|  | 						'blank' => $post_menu_blank[$category][$i] == 'on' ? 1 : 0, | ||||||
|  | 						'color' => str_replace('#', '', $post_menu_color[$category][$i]), | ||||||
|  | 						'category' => $category, | ||||||
|  | 						'ordering' => $i | ||||||
|  | 					]); | ||||||
|  | 				} catch (PDOException $error) { | ||||||
|  | 					warning('Error while adding menu item (' . $menu . '): ' . $error->getMessage()); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		onTemplateMenusChange(); | ||||||
|  | 		success('Saved at ' . date('H:i')); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$path = TEMPLATES . $template; | ||||||
|  |  | ||||||
|  | 	if (isset($pluginThemes[$template])) { | ||||||
|  | 		$path = BASE . $pluginThemes[$template]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$path .= '/config.php'; | ||||||
|  |  | ||||||
|  | 	if (file_exists($path)) { | ||||||
|  | 		require_once $path; | ||||||
|  | 	} else { | ||||||
|  | 		echo 'Cannot find template config.php file.'; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!isset($config['menu_categories'])) { | ||||||
|  | 		echo "No menu categories set in template config.php.<br/>This template doesn't support dynamic menus."; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (isset($_GET['reset_colors'])) { | ||||||
|  | 		foreach ($config['menu_categories'] as $id => $options) { | ||||||
|  | 			$color = $options['default_links_color'] ?? ($config['menu_default_links_color'] ?? ($config['menu_default_color'] ?? '#ffffff')); | ||||||
|  | 			Menu::where('template', $template)->where('category', $id)->update(['color' => str_replace('#', '', $color)]); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		onTemplateMenusChange(); | ||||||
|  | 		success('Colors has been reset at ' . date('H:i')); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (isset($_GET['reset_menus'])) { | ||||||
|  | 		$configMenus = config('menus'); | ||||||
|  | 		if (isset($configMenus)) { | ||||||
|  | 			Plugins::installMenus($template, config('menus'), true); | ||||||
|  |  | ||||||
|  | 			onTemplateMenusChange(); | ||||||
|  | 			success('Menus has been reset at ' . date('H:i')); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			error("This template don't support reinstalling menus."); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$title = 'Menus - ' . $template; | ||||||
|  |  | ||||||
|  | 	$canResetColors = isset($config['menu_default_color']) || isset($config['menu_default_links_color']); | ||||||
|  | 	foreach ($config['menu_categories'] as $id => $options) { | ||||||
|  | 		if (isset($options['default_links_color'])) { | ||||||
|  | 			$canResetColors = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$twig->display('admin.menus.header.html.twig', [ | ||||||
|  | 		'template' => $template, | ||||||
|  | 		'canResetColors' => $canResetColors | ||||||
|  | 	]); | ||||||
|  | 	?> | ||||||
|  | 	<?php | ||||||
|  | 	$menus = Menu::query() | ||||||
|  | 		->select('name', 'link', 'blank', 'color', 'category', 'ordering') | ||||||
|  | 		->where('enabled', 1) | ||||||
|  | 		->where('template', $template) | ||||||
|  | 		->orderBy('ordering') | ||||||
|  | 		->get() | ||||||
|  | 		->groupBy('category') | ||||||
|  | 		->toArray(); | ||||||
|  |  | ||||||
|  | 	$last_id = array(); | ||||||
|  | 	?> | ||||||
|  | 	<form method="post" id="menus-form" action="?p=menus"> | ||||||
|  | 		<?php csrf(); ?> | ||||||
|  | 		<input type="hidden" name="template" value="<?php echo $template ?>"/> | ||||||
|  | 		<button type="submit" name="save" class="btn btn-info">Save</button><br/><br/> | ||||||
|  | 		<div class="row"> | ||||||
|  | 			<?php foreach ($config['menu_categories'] as $id => $cat): ?> | ||||||
|  | 				<div class="col-md-12 col-lg-6"> | ||||||
|  | 					<div class="card card-info card-outline"> | ||||||
|  | 						<div class="card-header"> | ||||||
|  | 							<h5 class="m-0"><?php echo $cat['name'] ?> <i class="far fa-plus-square add-button" id="add-button-<?php echo $id ?>"></i></h5> | ||||||
|  | 						</div> | ||||||
|  | 						<div class="card-body"> | ||||||
|  | 							<ul class="sortable" id="sortable-<?php echo $id ?>"> | ||||||
|  | 								<?php | ||||||
|  | 								if (isset($menus[$id])) { | ||||||
|  | 									$i = 0; | ||||||
|  | 									foreach ($menus[$id] as $menu): | ||||||
|  | 										$color = (empty($menu['color']) ? ($cat['default_links_color'] ?? ($config['menu_default_links_color'] ?? ($config['menu_default_color'] ?? '#ffffff'))) : '#' . $menu['color']); | ||||||
|  | 										?> | ||||||
|  | 										<li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>"><label>Name:</label> <input type="text" name="menu[<?php echo $id ?>][]" value="<?php echo escapeHtml($menu['name']); ?>"/> | ||||||
|  | 											<label>Link:</label> <input type="text" name="menu_link[<?php echo $id ?>][]" value="<?php echo $menu['link'] ?>"/> | ||||||
|  | 											<input type="hidden" name="menu_blank[<?php echo $id ?>][]" value="0"/> | ||||||
|  | 											<label><input class="blank-checkbox" type="checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label> | ||||||
|  | 											<input class="color-picker" type="text" name="menu_color[<?php echo $id ?>][]" value="<?php echo $color; ?>"/> | ||||||
|  | 											<a class="remove-button" id="remove-button-<?php echo $id ?>-<?php echo $i ?>"><i class="fas fa-trash"></a></i></li> | ||||||
|  | 										<?php $i++; $last_id[$id] = $i; | ||||||
|  | 									endforeach; | ||||||
|  | 								} ?> | ||||||
|  | 							</ul> | ||||||
|  | 						</div> | ||||||
|  | 					</div> | ||||||
|  | 				</div> | ||||||
|  | 			<?php endforeach ?> | ||||||
|  | 		</div> | ||||||
|  | 		<div class="row pb-2"> | ||||||
|  | 			<div class="col-md-12"> | ||||||
|  | 				<button type="submit" name="save" class="btn btn-info">Save</button> | ||||||
|  | 				<?php | ||||||
|  | 				echo '<button type="button" class="btn btn-danger float-right" value="Cancel" onclick="window.location = \'' . ADMIN_URL . '?p=menus\';"><i class="fas fa-cancel"></i> Cancel</button>'; | ||||||
|  | 				?> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</form> | ||||||
|  | 	<?php | ||||||
|  | 	$twig->display('admin.menus.js.html.twig', array( | ||||||
|  | 		'menus' => $menus, | ||||||
|  | 		'last_id' => $last_id, | ||||||
|  | 	)); | ||||||
|  | 	?> | ||||||
|  | 	<?php | ||||||
|  | } else { | ||||||
|  | 	$templates = Menu::select('template')->distinct()->get()->toArray(); | ||||||
|  | 	foreach ($templates as $key => $value) { | ||||||
|  | 		$path = TEMPLATES . $value['template']; | ||||||
|  |  | ||||||
|  | 		if (isset($pluginThemes[$value['template']])) { | ||||||
|  | 			$path = BASE . $pluginThemes[$value['template']]; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (!file_exists($path . '/config.php')) { | ||||||
|  | 			unset($templates[$key]); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$twig->display('admin.menus.form.html.twig', array( | ||||||
|  | 		'templates' => $templates | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function onTemplateMenusChange(): void | ||||||
|  | { | ||||||
|  | 	$cache = Cache::getInstance(); | ||||||
|  | 	if ($cache->enabled()) { | ||||||
|  | 		$cache->delete('template_menus'); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								admin/pages/modules/balance.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,15 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Player; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $balance = 0; | ||||||
|  |  | ||||||
|  | if ($db->hasColumn('players', 'balance')) { | ||||||
|  | 	$balance = Player::orderByDesc('balance')->limit(10)->get(['id', 'name', 'balance'])->toArray(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('balance.html.twig', array( | ||||||
|  | 	'balance' => $balance | ||||||
|  | )); | ||||||
							
								
								
									
										20
									
								
								admin/pages/modules/coins.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,20 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Account; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $coins = 0; | ||||||
|  |  | ||||||
|  | if (HAS_ACCOUNT_COINS) { | ||||||
|  | 	$whatToGet = ['id', 'coins']; | ||||||
|  | 	if (USE_ACCOUNT_NAME) { | ||||||
|  | 		$whatToGet[] = 'name'; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$coins = Account::orderByDesc('coins')->limit(10)->get($whatToGet)->toArray(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('coins.html.twig', array( | ||||||
|  | 	'coins' => $coins | ||||||
|  | )); | ||||||
							
								
								
									
										15
									
								
								admin/pages/modules/created.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,15 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Account; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $accounts = 0; | ||||||
|  |  | ||||||
|  | if ($db->hasColumn('accounts', 'created')) { | ||||||
|  | 	$accounts = Account::orderByDesc('created')->limit(10)->get(['id', 'created'])->toArray(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('created.html.twig', array( | ||||||
|  | 	'accounts' => $accounts, | ||||||
|  | )); | ||||||
							
								
								
									
										0
									
								
								admin/pages/modules/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										15
									
								
								admin/pages/modules/lastlogin.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,15 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Player; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $players = 0; | ||||||
|  |  | ||||||
|  | if ($db->hasColumn('players', 'lastlogin')) { | ||||||
|  | 	$players = Player::orderByDesc('lastlogin')->limit(10)->get(['id', 'name', 'level', 'lastlogin'])->toArray(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('lastlogin.html.twig', array( | ||||||
|  | 	'players' => $players, | ||||||
|  | )); | ||||||
							
								
								
									
										15
									
								
								admin/pages/modules/points.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,15 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Account; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $points = 0; | ||||||
|  |  | ||||||
|  | if ($db->hasColumn('accounts', 'premium_points')) { | ||||||
|  | 	$coins = Account::orderByDesc('premium_points')->limit(10)->get(['premium_points', (USE_ACCOUNT_NAME ? 'name' : 'id')])->toArray(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('points.html.twig', array( | ||||||
|  | 	'points' => $points, | ||||||
|  | )); | ||||||
							
								
								
									
										46
									
								
								admin/pages/modules/server_status.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,46 @@ | |||||||
|  | <?php | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | if (isset($status)) { | ||||||
|  |  | ||||||
|  | 	$error_icon = '<i class="fas fa-exclamation-circle text-danger"></i>'; ?> | ||||||
|  | 	<div class=" col-md-6 col-lg-6"> | ||||||
|  | 		<div class="card card-info card-outline"> | ||||||
|  | 			<div class="card-header border-bottom-0"> | ||||||
|  | 				<span class="font-weight-bold m-0">Server Status</span> <span class="float-right small"><b>Last checked</b>: <?php echo(isset($status['lastCheck']) ? date("l, d.m.Y H:i:s", $status['lastCheck']) : $error_icon); ?></span> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="card-body p-0 "> | ||||||
|  | 				<table class="table"> | ||||||
|  | 					<tbody> | ||||||
|  | 					<tr> | ||||||
|  | 						<th width="30%">Server</th> | ||||||
|  | 						<td><?php echo(isset($status['server']) & isset($status['serverVersion']) ? $status['server'] . ' x ' . $status['serverVersion'] : $error_icon) ?></td> | ||||||
|  |  | ||||||
|  | 					</tr> | ||||||
|  | 					<tr> | ||||||
|  | 						<th>Client</th> | ||||||
|  | 						<td><?php echo(isset($status['clientVersion']) ? $status['clientVersion'] : $error_icon) ?></td> | ||||||
|  | 					</tr> | ||||||
|  | 					<tr> | ||||||
|  | 						<th>Map</th> | ||||||
|  | 						<td> | ||||||
|  | 							<?php if (isset($status['mapName']) & isset($status['mapAuthor']) & isset($status['mapWidth']) & isset($status['mapHeight'])) { | ||||||
|  | 								echo $status['mapName'] . ' by <b>' . $status['mapAuthor'] . '</b><br/>' . $status['mapWidth'] . ' x ' . $status['mapHeight']; | ||||||
|  | 							} else { | ||||||
|  | 								echo $error_icon; | ||||||
|  | 							} ?> | ||||||
|  | 						</td> | ||||||
|  | 					</tr> | ||||||
|  | 					<tr> | ||||||
|  | 						<th>Monsters</th> | ||||||
|  | 						<td><?php echo (isset($status['monsters']) ? $status['monsters'] : $error_icon); ?></td> | ||||||
|  | 					</tr> | ||||||
|  | 					<tr> | ||||||
|  | 						<th>MOTD:</th> | ||||||
|  | 						<td><?php echo(isset($status['motd']) ? $status['motd'] : $error_icon); ?></td> | ||||||
|  | 					</tr> | ||||||
|  | 					</tbody> | ||||||
|  | 				</table> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | <?php } ?> | ||||||
							
								
								
									
										21
									
								
								admin/pages/modules/statistics.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,21 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Account; | ||||||
|  | use MyAAC\Models\Guild; | ||||||
|  | use MyAAC\Models\House; | ||||||
|  | use MyAAC\Models\Monster; | ||||||
|  | use MyAAC\Models\Player; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $count = $eloquentConnection->query() | ||||||
|  | 	->select([ | ||||||
|  | 		'total_accounts' => Account::selectRaw('COUNT(id)'), | ||||||
|  | 		'total_players' => Player::selectRaw('COUNT(id)'), | ||||||
|  | 		'total_guilds' => Guild::selectRaw('COUNT(id)'), | ||||||
|  | 		'total_monsters' => Monster::selectRaw('COUNT(id)'), | ||||||
|  | 		'total_houses' => House::selectRaw('COUNT(id)'), | ||||||
|  | 	])->first(); | ||||||
|  |  | ||||||
|  | $twig->display('statistics.html.twig', array( | ||||||
|  | 	'count' => $count, | ||||||
|  | )); | ||||||
							
								
								
									
										31
									
								
								admin/pages/modules/templates/balance.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | |||||||
|  | {% if balance is iterable %} | ||||||
|  | 	<div class=" col-md-6 col-lg-3"> | ||||||
|  | 		<div class="card card-info card-outline"> | ||||||
|  | 			<div class="card-header"> | ||||||
|  | 				<h5 class="m-0">Top 10 - Balance</h5> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="card-body p-0"> | ||||||
|  | 				<table class="table table-striped table-condensed"> | ||||||
|  | 					<thead> | ||||||
|  | 					<tr> | ||||||
|  | 						<th>#</th> | ||||||
|  | 						<th>Player</th> | ||||||
|  | 						<th>Balance</th> | ||||||
|  | 					</tr> | ||||||
|  | 					</thead> | ||||||
|  | 					<tbody> | ||||||
|  | 					{% set i = 0 %} | ||||||
|  | 					{% for result in balance %} | ||||||
|  | 						{% set i = i + 1 %} | ||||||
|  | 						<tr> | ||||||
|  | 							<th>{{ i }}</th> | ||||||
|  | 							<td><a href="?p=players&id={{ result.id }}">{{ result.name }}</a></td> | ||||||
|  | 							<td>{{ result.balance }}</td> | ||||||
|  | 						</tr> | ||||||
|  | 					{% endfor %} | ||||||
|  | 					</tbody> | ||||||
|  | 				</table> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | {% endif %} | ||||||
							
								
								
									
										31
									
								
								admin/pages/modules/templates/coins.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | |||||||
|  | {% if coins is iterable %} | ||||||
|  | 	<div class=" col-md-6 col-lg-3"> | ||||||
|  | 		<div class="card card-info card-outline"> | ||||||
|  | 			<div class="card-header"> | ||||||
|  | 				<h5 class="m-0">Top 10 - Most coins</h5> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="card-body p-0"> | ||||||
|  | 				<table class="table table-striped table-condensed"> | ||||||
|  | 					<thead> | ||||||
|  | 					<tr> | ||||||
|  | 						<th>#</th> | ||||||
|  | 						<th>Account</th> | ||||||
|  | 						<th>Tibia coins</th> | ||||||
|  | 					</tr> | ||||||
|  | 					</thead> | ||||||
|  | 					<tbody> | ||||||
|  | 					{% set i = 0 %} | ||||||
|  | 					{% for result in coins %} | ||||||
|  | 						{% set i = i + 1 %} | ||||||
|  | 						<tr> | ||||||
|  | 							<th>{{ i }}</th> | ||||||
|  | 							<td><a href="?p=accounts&id={{ result.id }}">{{ result.name ?? result.id }}</a></td> | ||||||
|  | 							<td>{{ result.coins }}</td> | ||||||
|  | 						</tr> | ||||||
|  | 					{% endfor %} | ||||||
|  | 					</tbody> | ||||||
|  | 				</table> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | {% endif %} | ||||||
							
								
								
									
										31
									
								
								admin/pages/modules/templates/created.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | |||||||
|  | {% if accounts is iterable %} | ||||||
|  | 	<div class=" col-md-6 col-lg-3"> | ||||||
|  | 		<div class="card card-info card-outline"> | ||||||
|  | 			<div class="card-header"> | ||||||
|  | 				<h5 class="m-0">Last 10 created</h5> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="card-body p-0"> | ||||||
|  | 				<table class="table table-striped table-condensed"> | ||||||
|  | 					<thead> | ||||||
|  | 					<tr> | ||||||
|  | 						<th>#</th> | ||||||
|  | 						<th>Account</th> | ||||||
|  | 						<th>Creation Date</th> | ||||||
|  | 					</tr> | ||||||
|  | 					</thead> | ||||||
|  | 					<tbody> | ||||||
|  | 					{% set i = 0 %} | ||||||
|  | 					{% for result in accounts %} | ||||||
|  | 						{% set i = i + 1 %} | ||||||
|  | 						<tr> | ||||||
|  | 							<th>{{ i }}</th> | ||||||
|  | 							<td><a href="?p=accounts&id={{ result.id }}">{{ result.id }}</a></td> | ||||||
|  | 							<td>{{ result.created|date("M d Y, H:i:s") }}</td> | ||||||
|  | 						</tr> | ||||||
|  | 					{% endfor %} | ||||||
|  | 					</tbody> | ||||||
|  | 				</table> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | {% endif %} | ||||||
							
								
								
									
										0
									
								
								admin/pages/modules/templates/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										31
									
								
								admin/pages/modules/templates/lastlogin.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | |||||||
|  | {% if players is iterable %} | ||||||
|  | 	<div class=" col-md-6 col-lg-3"> | ||||||
|  | 		<div class="card card-info card-outline"> | ||||||
|  | 			<div class="card-header"> | ||||||
|  | 				<h5 class="m-0">Last 10 logins</h5> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="card-body p-0"> | ||||||
|  | 				<table class="table table-striped table-condensed"> | ||||||
|  | 					<thead> | ||||||
|  | 					<tr> | ||||||
|  | 						<th>#</th> | ||||||
|  | 						<th>Player</th> | ||||||
|  | 						<th>Login Date</th> | ||||||
|  | 					</tr> | ||||||
|  | 					</thead> | ||||||
|  | 					<tbody> | ||||||
|  | 					{% set i = 0 %} | ||||||
|  | 					{% for result in players %} | ||||||
|  | 						{% set i = i + 1 %} | ||||||
|  | 						<tr> | ||||||
|  | 							<th>{{ i }}</th> | ||||||
|  | 							<td><a href="?p=players&id={{ result.id }}">{{ result.name }}</a></td> | ||||||
|  | 							<td>{{ result.lastlogin|date("M d Y, H:i:s") }}</td> | ||||||
|  | 						</tr> | ||||||
|  | 					{% endfor %} | ||||||
|  | 					</tbody> | ||||||
|  | 				</table> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | {% endif %} | ||||||
							
								
								
									
										31
									
								
								admin/pages/modules/templates/points.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | |||||||
|  | {% if points is iterable %} | ||||||
|  | 	<div class=" col-md-6 col-lg-3"> | ||||||
|  | 		<div class="card card-info card-outline"> | ||||||
|  | 			<div class="card-header"> | ||||||
|  | 				<h5 class="m-0">Top 10 - Most premium points</h5> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="card-body p-0"> | ||||||
|  | 				<table class="table table-striped table-condensed"> | ||||||
|  | 					<thead> | ||||||
|  | 					<tr> | ||||||
|  | 						<th>#</th> | ||||||
|  | 						<th>Account</th> | ||||||
|  | 						<th>Premium points</th> | ||||||
|  | 					</tr> | ||||||
|  | 					</thead> | ||||||
|  | 					<tbody> | ||||||
|  | 					{% set i = 0 %} | ||||||
|  | 					{% for result in points %} | ||||||
|  | 						{% set i = i + 1 %} | ||||||
|  | 						<tr> | ||||||
|  | 							<th>{{ i }}</th> | ||||||
|  | 							<td><a href="?p=accounts&id={{ result.id }}">{{ result.name }}</a></td> | ||||||
|  | 							<td>{{ result.premium_points }}</td> | ||||||
|  | 						</tr> | ||||||
|  | 					{% endfor %} | ||||||
|  | 					</tbody> | ||||||
|  | 				</table> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | {% endif %} | ||||||
							
								
								
									
										45
									
								
								admin/pages/modules/templates/statistics.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,45 @@ | |||||||
|  | <div class="col"> | ||||||
|  | 	<div class="info-box"> | ||||||
|  | 		<span class="info-box-icon bg-info elevation-1"><i class="fas fa-user-plus"></i></span> | ||||||
|  | 		<div class="info-box-content"> | ||||||
|  | 			<span class="info-box-text">Accounts:</span> | ||||||
|  | 			<span class="info-box-number">{{ count.total_accounts }}</span> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  | <div class="col"> | ||||||
|  | 	<div class="info-box"> | ||||||
|  | 		<span class="info-box-icon bg-red elevation-1"><i class="fas fa-user-plus"></i></span> | ||||||
|  | 		<div class="info-box-content"> | ||||||
|  | 			<span class="info-box-text">Players:</span> | ||||||
|  | 			<span class="info-box-number">{{ count.total_players }}</span> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  | <div class="col"> | ||||||
|  | 	<div class="info-box"> | ||||||
|  | 		<span class="info-box-icon bg-teal elevation-1"><i class="fas fa-pastafarianism"></i></span> | ||||||
|  | 		<div class="info-box-content"> | ||||||
|  | 			<span class="info-box-text">Monsters:</span> | ||||||
|  | 			<span class="info-box-number">{{ count.total_monsters }}</span> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  | <div class="col"> | ||||||
|  | 	<div class="info-box"> | ||||||
|  | 		<span class="info-box-icon bg-green elevation-1"><i class="fas fa-chart-pie"></i></span> | ||||||
|  | 		<div class="info-box-content"> | ||||||
|  | 			<span class="info-box-text">Guilds:</span> | ||||||
|  | 			<span class="info-box-number">{{ count.total_guilds }}</span> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  | <div class="col"> | ||||||
|  | 	<div class="info-box"> | ||||||
|  | 		<span class="info-box-icon bg-yellow elevation-1"><i class="fas fa-home"></i></span> | ||||||
|  | 		<div class="info-box-content"> | ||||||
|  | 			<span class="info-box-text">Houses:</span> | ||||||
|  | 			<span class="info-box-number">{{ count.total_houses }}</span> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
							
								
								
									
										43
									
								
								admin/pages/modules/templates/web_status.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,43 @@ | |||||||
|  | <div class="col-12 col-md-6"> | ||||||
|  | 	<div class="card card-warning card-outline"> | ||||||
|  | 		<div class="card-header"> | ||||||
|  | 			<span class="m-0">Website Status<span class="float-right"> | ||||||
|  | 			<div class="custom-control custom-switch custom-switch-off-danger custom-switch-on-success"> | ||||||
|  | 				<input form="maintenance-form" type="checkbox" class="custom-control-input" name="status" id="status" value="true" {% if not is_closed %} checked{% endif %}> | ||||||
|  | 				<label id="status-label" class="custom-control-label" for="status"> {% if is_closed %}Closed{% else %}Open{% endif %}</label> | ||||||
|  | 			</div></span> | ||||||
|  | 			</span> | ||||||
|  | 		</div> | ||||||
|  | 		<div class="card-body p-2"> | ||||||
|  | 			<div class="col-sm-12"> | ||||||
|  | 				<label for="message" class="col-form-label">Maintenance Message</label> | ||||||
|  | 				<textarea form="maintenance-form" name="message" class="form-control" cols="40" rows="3" maxlength="255" placeholder="Enter ...">{{ closed_message }}</textarea> | ||||||
|  | 				<small>(only visible if closed)</small> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 		<div class="card-footer"> | ||||||
|  | 			<form id="maintenance-form" method="post" action="?p=dashboard" class="float-left"> | ||||||
|  | 				{{ csrf() }} | ||||||
|  | 				<input type="hidden" name="maintenance" value="1" /> | ||||||
|  | 				<button type="submit" class="btn btn-info"><i class="far fa-update"></i> Update</button> | ||||||
|  | 			</form> | ||||||
|  | 			<form method="post" action="?p=dashboard" class="float-right"> | ||||||
|  | 				{{ csrf() }} | ||||||
|  | 				<input type="hidden" name="clear_cache" value="1" /> | ||||||
|  | 				<button type="submit" onclick="return confirm('Are you sure that you want to clear cache?');" class="btn btn-danger" title="Clear Cache"><i class="fas fa-clear"></i>Clear cache</button> | ||||||
|  | 			</form> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | 	$(function() { | ||||||
|  | 		$("#status").change(function() { | ||||||
|  | 			$statusLabel = $("#status-label"); | ||||||
|  | 			$statusLabel.html("Closed"); | ||||||
|  | 			if ($(this).is(':checked')) { | ||||||
|  | 				$statusLabel.html("Open"); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 	}); | ||||||
|  | </script> | ||||||
							
								
								
									
										10
									
								
								admin/pages/modules/web_status.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,10 @@ | |||||||
|  | <?php | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $twig->display('web_status.twig', array( | ||||||
|  | 	'is_closed' => $is_closed, | ||||||
|  | 	'closed_message' => $closed_message, | ||||||
|  | 	'status' => $status, | ||||||
|  | 	'account_type' => USE_ACCOUNT_NAME ? 'name' : 'number' | ||||||
|  | )); | ||||||
|  | ?> | ||||||
							
								
								
									
										165
									
								
								admin/pages/news.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,165 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Pages | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Forum; | ||||||
|  | use MyAAC\News; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $title = 'News Panel'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | $use_datatable = true; | ||||||
|  |  | ||||||
|  | if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) { | ||||||
|  | 	echo 'Access denied.'; | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | header('X-XSS-Protection:0'); | ||||||
|  |  | ||||||
|  | // some constants, used mainly by database (cannot be modified without schema changes) | ||||||
|  | const NEWS_TITLE_LIMIT = 100; | ||||||
|  | const NEWS_BODY_LIMIT = 65535; // maximum news body length | ||||||
|  | const ARTICLE_TEXT_LIMIT = 300; | ||||||
|  | const ARTICLE_IMAGE_LIMIT = 100; | ||||||
|  |  | ||||||
|  | $name = $p_title = ''; | ||||||
|  | if(!empty($action)) | ||||||
|  | { | ||||||
|  | 	$id = $_POST['id'] ?? null; | ||||||
|  | 	$p_title = $_POST['title'] ?? null; | ||||||
|  | 	$body = isset($_POST['body']) ? stripslashes($_POST['body']) : null; | ||||||
|  | 	$comments = $_POST['comments'] ?? null; | ||||||
|  | 	$type = isset($_REQUEST['type']) ? (int)$_REQUEST['type'] : 1; | ||||||
|  | 	$category = isset($_POST['category']) ? (int)$_POST['category'] : null; | ||||||
|  | 	$player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : null; | ||||||
|  | 	$article_text = $_POST['article_text'] ?? null; | ||||||
|  | 	$article_image = $_POST['article_image'] ?? null; | ||||||
|  | 	$forum_section = $_POST['forum_section'] ?? null; | ||||||
|  | 	$errors = []; | ||||||
|  |  | ||||||
|  | 	if (isRequestMethod('post')) { | ||||||
|  | 		if ($action == 'new') { | ||||||
|  | 			if (isset($forum_section) && $forum_section != '-1') { | ||||||
|  | 				$forum_add = Forum::add_thread($p_title, $body, $forum_section, $player_id, $account_logged->getId(), $errors); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (isset($p_title) && News::add($p_title, $body, $type, $category, $player_id, isset($forum_add) && $forum_add != 0 ? $forum_add : 0, $article_text, $article_image, $errors)) { | ||||||
|  | 				$p_title = $body = $comments = $article_text = $article_image = ''; | ||||||
|  | 				$type = $category = $player_id = 0; | ||||||
|  |  | ||||||
|  | 				success('Added successful.'); | ||||||
|  | 			} | ||||||
|  | 		} else if ($action == 'delete') { | ||||||
|  | 			if (News::delete($id, $errors)) { | ||||||
|  | 				success('Deleted successful.'); | ||||||
|  | 			} | ||||||
|  | 		} else if ($action == 'edit') { | ||||||
|  | 			if (isset($id) && !isset($p_title)) { | ||||||
|  | 				$news = News::get($id); | ||||||
|  | 				$p_title = $news['title']; | ||||||
|  | 				$body = $news['body']; | ||||||
|  | 				$comments = $news['comments']; | ||||||
|  | 				$type = $news['type']; | ||||||
|  | 				$category = $news['category']; | ||||||
|  | 				$player_id = $news['player_id']; | ||||||
|  | 				$article_text = $news['article_text']; | ||||||
|  | 				$article_image = $news['article_image']; | ||||||
|  | 			} else { | ||||||
|  | 				if (News::update($id, $p_title, $body, $type, $category, $player_id, $forum_section, $article_text, $article_image, $errors)) { | ||||||
|  | 					// update forum thread if exists | ||||||
|  | 					if (isset($forum_section) && Validator::number($forum_section)) { | ||||||
|  | 						$db->query("UPDATE `" . TABLE_PREFIX . "forum` SET `author_guid` = " . (int)$player_id . ", `post_text` = " . $db->quote($body) . ", `post_topic` = " . $db->quote($p_title) . ", `edit_date` = " . time() . " WHERE `id` = " . $db->quote($forum_section)); | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					$action = $p_title = $body = $comments = $article_text = $article_image = ''; | ||||||
|  | 					$type = $category = $player_id = 0; | ||||||
|  |  | ||||||
|  | 					success('Updated successful.'); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} else if ($action == 'hide') { | ||||||
|  | 			if (News::toggleHide($id, $errors, $status)) { | ||||||
|  | 				success(($status == 1 ? 'Hide' : 'Show') . ' successful.'); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if(!empty($errors)) | ||||||
|  | 		error(implode(", ", $errors)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $categories = array(); | ||||||
|  | foreach($db->query('SELECT `id`, `name`, `icon_id` FROM `' . TABLE_PREFIX . 'news_categories` WHERE `hide` != 1') as $cat) | ||||||
|  | { | ||||||
|  | 	$categories[$cat['id']] = array( | ||||||
|  | 		'name' => $cat['name'], | ||||||
|  | 		'icon_id' => $cat['icon_id'] | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if($action == 'edit' || $action == 'new') { | ||||||
|  | 	if($action == 'edit') { | ||||||
|  | 		$player = new OTS_Player(); | ||||||
|  | 		$player->load($player_id); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$account_players = $account_logged->getPlayersList(); | ||||||
|  | 	$account_players->orderBy('group_id', POT::ORDER_DESC); | ||||||
|  | 	$twig->display('admin.news.form.html.twig', array( | ||||||
|  | 		'action' => $action, | ||||||
|  | 		'news_id' => $id ?? null, | ||||||
|  | 		'title' => $p_title ?? '', | ||||||
|  | 		'body' => isset($body) ? escapeHtml($body) : '', | ||||||
|  | 		'type' => $type, | ||||||
|  | 		'player' => isset($player) && $player->isLoaded() ? $player : null, | ||||||
|  | 		'player_id' => $player_id ?? null, | ||||||
|  | 		'account_players' => $account_players, | ||||||
|  | 		'category' => $category ?? 0, | ||||||
|  | 		'categories' => $categories, | ||||||
|  | 		'forum_boards' => getForumBoards(), | ||||||
|  | 		'forum_section' => $forum_section ?? null, | ||||||
|  | 		'comments' => $comments ?? null, | ||||||
|  | 		'article_text' => $article_text ?? null, | ||||||
|  | 		'article_image' => $article_image ?? null | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $query = $db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'news')); | ||||||
|  | $newses = array(); | ||||||
|  |  | ||||||
|  | $cachePlayers = []; | ||||||
|  | foreach ($query as $_news) { | ||||||
|  | 	$playerId = $_news['player_id']; | ||||||
|  | 	if (isset($cachePlayers[$playerId])) { | ||||||
|  | 		$_player = $cachePlayers[$playerId]; | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		$_player = new OTS_Player(); | ||||||
|  | 		$_player->load($playerId); | ||||||
|  | 		$cachePlayers[$playerId] = $_player; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$newses[$_news['type']][] = array( | ||||||
|  | 		'id' => $_news['id'], | ||||||
|  | 		'hide' => $_news['hide'], | ||||||
|  | 		'archive_link' => getLink('news') . '/archive/' . $_news['id'], | ||||||
|  | 		'title' => $_news['title'], | ||||||
|  | 		'date' => $_news['date'], | ||||||
|  | 		'player_name' => $_player->isLoaded() ? $_player->getName() : '', | ||||||
|  | 		'player_link' => $_player->isLoaded() ? getPlayerLink($_player, false) : '', | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('admin.news.html.twig', array( | ||||||
|  | 	'newses' => $newses | ||||||
|  | )); | ||||||
							
								
								
									
										41
									
								
								admin/pages/notepad.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,41 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Notepad | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Notepad as ModelsNotepad; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Notepad'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @var OTS_Account $account_logged | ||||||
|  |  */ | ||||||
|  | $_content = ''; | ||||||
|  | $notepad = ModelsNotepad::where('account_id', $account_logged->getId())->first(); | ||||||
|  | if (isset($_POST['content'])) { | ||||||
|  | 	$_content = html_entity_decode(stripslashes($_POST['content'])); | ||||||
|  | 	if (!$notepad) { | ||||||
|  | 		ModelsNotepad::create([ | ||||||
|  | 			'account_id' => $account_logged->getId(), | ||||||
|  | 			'content' => $_content | ||||||
|  | 		]); | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		ModelsNotepad::where('account_id', $account_logged->getId())->update(['content' => $_content]); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	success('Saved at ' . date('H:i')); | ||||||
|  | } else { | ||||||
|  | 	if ($notepad) | ||||||
|  | 		$_content = $notepad->content; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('admin.notepad.html.twig', ['content' => $_content]); | ||||||
							
								
								
									
										14
									
								
								admin/pages/open_source.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,14 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Open Source libraries | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2023 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $title = 'Open Source'; | ||||||
|  |  | ||||||
|  | $twig->display('admin.open_source.html.twig'); | ||||||
							
								
								
									
										133
									
								
								admin/pages/pages.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,133 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Pages | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Pages as ModelsPages; | ||||||
|  | use MyAAC\Admin\Pages; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Pages'; | ||||||
|  | $use_datatable = true; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) { | ||||||
|  | 	echo 'Access denied.'; | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | header('X-XSS-Protection:0'); | ||||||
|  |  | ||||||
|  | $name = $p_title = null; | ||||||
|  | $groups = new OTS_Groups_List(); | ||||||
|  |  | ||||||
|  | $php = false; | ||||||
|  | $enable_tinymce = true; | ||||||
|  | $access = 0; | ||||||
|  |  | ||||||
|  | // some constants, used mainly by database (cannot by modified without schema changes) | ||||||
|  | const PAGE_TITLE_LIMIT = 30; | ||||||
|  | const PAGE_NAME_LIMIT = 30; | ||||||
|  | const PAGE_BODY_LIMIT = 65535; // maximum page body length | ||||||
|  |  | ||||||
|  | if (!empty($action) && isRequestMethod('post')) { | ||||||
|  | 	if ($action == 'delete' || $action == 'edit' || $action == 'hide') { | ||||||
|  | 		$id = $_POST['id']; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (isset($_POST['name'])) { | ||||||
|  | 		$name = $_POST['name']; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (isset($_POST['title'])) { | ||||||
|  | 		$p_title = $_POST['title']; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$php = isset($_POST['php']) && $_POST['php'] == 1; | ||||||
|  | 	$enable_tinymce = (isset($_POST['enable_tinymce']) && $_POST['enable_tinymce'] == 1) ?: $enable_tinymce; | ||||||
|  | 	if ($php) { | ||||||
|  | 		$body = $_POST['body']; | ||||||
|  | 	} | ||||||
|  | 	else if (isset($_POST['body'])) { | ||||||
|  | 		//$body = $_POST['body']; | ||||||
|  | 		$body = html_entity_decode(stripslashes($_POST['body'])); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (isset($_POST['access'])) { | ||||||
|  | 		$access = $_POST['access']; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$errors = array(); | ||||||
|  | 	$player_id = 1; | ||||||
|  |  | ||||||
|  | 	if ($action == 'new') { | ||||||
|  | 		if (isset($p_title) && Pages::add($name, $p_title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) { | ||||||
|  | 			$name = $p_title = $body = ''; | ||||||
|  | 			$player_id = $access = 0; | ||||||
|  | 			$php = false; | ||||||
|  | 			$enable_tinymce = true; | ||||||
|  | 			success('Added successful.'); | ||||||
|  | 		} | ||||||
|  | 	} else if ($action == 'delete') { | ||||||
|  | 		if (Pages::delete($id, $errors)) | ||||||
|  | 			success('Page with id ' . $id . ' has been deleted'); | ||||||
|  | 	} else if ($action == 'edit') { | ||||||
|  | 		if (isset($id) && !isset($_POST['name'])) { | ||||||
|  | 			$_page = Pages::get($id); | ||||||
|  | 			$name = $_page['name']; | ||||||
|  | 			$p_title = $_page['title']; | ||||||
|  | 			$body = $_page['body']; | ||||||
|  | 			$php = $_page['php'] == '1'; | ||||||
|  | 			$enable_tinymce = $_page['enable_tinymce'] == '1'; | ||||||
|  | 			$access = $_page['access']; | ||||||
|  | 		} else { | ||||||
|  | 			if(Pages::update($id, $name, $p_title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) { | ||||||
|  | 				$action = $name = $p_title = $body = ''; | ||||||
|  | 				$player_id = 1; | ||||||
|  | 				$access = 0; | ||||||
|  | 				$php = false; | ||||||
|  | 				$enable_tinymce = true; | ||||||
|  | 				success('Updated successful.'); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} else if ($action == 'hide') { | ||||||
|  | 		if (Pages::toggleHide($id, $errors, $status)) { | ||||||
|  | 			success(($status == 0 ? 'Show' : 'Hide') . ' successful.'); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!empty($errors)) | ||||||
|  | 		error(implode(", ", $errors)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $pages = ModelsPages::all()->map(function ($e) { | ||||||
|  | 	return [ | ||||||
|  | 		'link' => getFullLink($e->name, $e->name, true), | ||||||
|  | 		'title' => substr($e->title, 0, 20), | ||||||
|  | 		'php' => $e->php == '1', | ||||||
|  | 		'id' => $e->id, | ||||||
|  | 		'hide' => $e->hide | ||||||
|  | 	]; | ||||||
|  | })->toArray(); | ||||||
|  |  | ||||||
|  | $twig->display('admin.pages.form.html.twig', [ | ||||||
|  | 	'action' => $action, | ||||||
|  | 	'id' => $action == 'edit' ? $id : null, | ||||||
|  | 	'name' => $name, | ||||||
|  | 	'title' => $p_title, | ||||||
|  | 	'php' => $php, | ||||||
|  | 	'enable_tinymce' => $enable_tinymce, | ||||||
|  | 	'body' => isset($body) ? escapeHtml($body) : '', | ||||||
|  | 	'groups' => $groups->getGroups(), | ||||||
|  | 	'access' => $access | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | $twig->display('admin.pages.html.twig', [ | ||||||
|  | 	'pages' => $pages | ||||||
|  | ]); | ||||||
							
								
								
									
										19
									
								
								admin/pages/phpinfo.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,19 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * PHP Info | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'PHP Info'; | ||||||
|  |  | ||||||
|  | if (!function_exists('phpinfo')) { ?> | ||||||
|  | 	<b>phpinfo()</b> function is disabled in your webserver config.<br/> | ||||||
|  | 	You can enable it by editing <b>php.ini</b> file. | ||||||
|  | 	<?php return; | ||||||
|  | } | ||||||
|  | ?> | ||||||
|  | <iframe src="<?php echo ADMIN_URL; ?>tools/phpinfo.php" width="1024" height="550"></iframe> | ||||||
							
								
								
									
										910
									
								
								admin/pages/players.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,910 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Players editor | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Forum; | ||||||
|  | use MyAAC\Models\Player; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | $title = 'Player editor'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | $player_base = ADMIN_URL . '?p=players'; | ||||||
|  |  | ||||||
|  | $use_datatable = true; | ||||||
|  |  | ||||||
|  | $skills = array( | ||||||
|  | 	POT::SKILL_FIST => array('Fist fighting', 'fist'), | ||||||
|  | 	POT::SKILL_CLUB => array('Club fighting', 'club'), | ||||||
|  | 	POT::SKILL_SWORD => array('Sword fighting', 'sword'), | ||||||
|  | 	POT::SKILL_AXE => array('Axe fighting', 'axe'), | ||||||
|  | 	POT::SKILL_DIST => array('Distance fighting', 'dist'), | ||||||
|  | 	POT::SKILL_SHIELD => array('Shielding', 'shield'), | ||||||
|  | 	POT::SKILL_FISH => array('Fishing', 'fish') | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | $hasBlessingsColumn = $db->hasColumn('players', 'blessings'); | ||||||
|  | $hasBlessingColumn = $db->hasColumn('players', 'blessings1'); | ||||||
|  | $hasLookAddons = $db->hasColumn('players', 'lookaddons'); | ||||||
|  |  | ||||||
|  | $skull_type = array("None", "Yellow", "Green", "White", "Red", "Black", "Orange"); | ||||||
|  | ?> | ||||||
|  |  | ||||||
|  | <link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ > | ||||||
|  | <script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script> | ||||||
|  |  | ||||||
|  | <?php | ||||||
|  | $id = 0; | ||||||
|  | $search_player = ''; | ||||||
|  | if (isset($_REQUEST['id'])) | ||||||
|  | 	$id = (int)$_REQUEST['id']; | ||||||
|  | else if (isset($_REQUEST['search'])) { | ||||||
|  | 	$search_player = $_REQUEST['search']; | ||||||
|  | 	if (strlen($search_player) < 3 && !Validator::number($search_player)) { | ||||||
|  | 		echo_error('Player name is too short.'); | ||||||
|  | 	} else { | ||||||
|  | 		$query = Player::where('name', 'like', '%' . $search_player . '%')->orderBy('name')->limit(11)->get(['id', 'name']); | ||||||
|  | 		if (count($query) == 0) { | ||||||
|  | 			echo_error('No entries found.'); | ||||||
|  | 		} else if (count($query) == 1) { | ||||||
|  | 			$id = $query->first()->getKey(); | ||||||
|  | 		} else if (count($query) > 10) { | ||||||
|  | 			echo_error('Specified name resulted with too many players.'); | ||||||
|  | 		} else { | ||||||
|  | 			$str_construct = 'Do you mean?<ul>'; | ||||||
|  | 			foreach ($query as $row) { | ||||||
|  | 				$str_construct .= '<li><a href="' . $player_base . '&id=' . $row->getKey() . '">' . $row->name . '</a></li>'; | ||||||
|  | 			} | ||||||
|  | 			$str_construct .= '</ul>'; | ||||||
|  | 			echo_error($str_construct); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | ?> | ||||||
|  | <div class="row"> | ||||||
|  | 	<?php | ||||||
|  | 	$groups = new OTS_Groups_List(); | ||||||
|  | 	if ($id > 0) { | ||||||
|  | 		$player = new OTS_Player(); | ||||||
|  | 		$player->load($id); | ||||||
|  |  | ||||||
|  | 		if ($player->isLoaded() && isset($_POST['save'])) {// we want to save | ||||||
|  | 			$error = false; | ||||||
|  |  | ||||||
|  | 			if ($player->isOnline()) | ||||||
|  | 				echo_error('This player is actually online. You can\'t edit online players.'); | ||||||
|  |  | ||||||
|  | 			$name = $_POST['name']; | ||||||
|  | 			$_error = ''; | ||||||
|  | 			if (!Validator::characterName($name)) | ||||||
|  | 				echo_error(Validator::getLastError()); | ||||||
|  |  | ||||||
|  | 			//if(!Validator::newCharacterName($name) | ||||||
|  | 			//	echo_error(Validator::getLastError()); | ||||||
|  |  | ||||||
|  | 			$player_db = new OTS_Player(); | ||||||
|  | 			$player_db->find($name); | ||||||
|  | 			if ($player_db->isLoaded() && $player->getName() != $name) | ||||||
|  | 				echo_error('This name is already used. Please choose another name!'); | ||||||
|  |  | ||||||
|  | 			$account_id = $_POST['account_id']; | ||||||
|  | 			verify_number($account_id, 'Account id', 11); | ||||||
|  |  | ||||||
|  | 			$account_db = new OTS_Account(); | ||||||
|  | 			$account_db->load($account_id); | ||||||
|  | 			if (!$account_db->isLoaded()) | ||||||
|  | 				echo_error('Account with this id doesn\'t exist.'); | ||||||
|  |  | ||||||
|  | 			$group = $_POST['group']; | ||||||
|  | 			if ($groups->getGroup($group) == false) | ||||||
|  | 				echo_error('Group with this id doesn\'t exist'); | ||||||
|  |  | ||||||
|  | 			$level = $_POST['level']; | ||||||
|  | 			verify_number($level, 'Level', 11); | ||||||
|  |  | ||||||
|  | 			$experience = $_POST['experience']; | ||||||
|  | 			verify_number($experience, 'Experience', 20); | ||||||
|  |  | ||||||
|  | 			$vocation = $_POST['vocation']; | ||||||
|  | 			verify_number($vocation, 'Vocation id', 11); | ||||||
|  |  | ||||||
|  | 			if (!isset($config['vocations'][$vocation])) { | ||||||
|  | 				echo_error("Vocation with this id doesn't exist."); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// health | ||||||
|  | 			$health = $_POST['health']; | ||||||
|  | 			verify_number($health, 'Health', 11); | ||||||
|  | 			$health_max = $_POST['health_max']; | ||||||
|  | 			verify_number($health_max, 'Health max', 11); | ||||||
|  |  | ||||||
|  | 			// mana | ||||||
|  | 			$magic_level = $_POST['magic_level']; | ||||||
|  | 			verify_number($magic_level, 'Magic_level', 11); | ||||||
|  | 			$mana = $_POST['mana']; | ||||||
|  | 			verify_number($mana, 'Mana', 11); | ||||||
|  | 			$mana_max = $_POST['mana_max']; | ||||||
|  | 			verify_number($mana_max, 'Mana max', 11); | ||||||
|  | 			$mana_spent = $_POST['mana_spent']; | ||||||
|  | 			verify_number($mana_spent, 'Mana spent', 11); | ||||||
|  |  | ||||||
|  | 			// look | ||||||
|  | 			$look_body = $_POST['look_body']; | ||||||
|  | 			verify_number($look_body, 'Look body', 11); | ||||||
|  | 			$look_feet = $_POST['look_feet']; | ||||||
|  | 			verify_number($look_feet, 'Look feet', 11); | ||||||
|  | 			$look_head = $_POST['look_head']; | ||||||
|  | 			verify_number($look_head, 'Look head', 11); | ||||||
|  | 			$look_legs = $_POST['look_legs']; | ||||||
|  | 			verify_number($look_legs, 'Look legs', 11); | ||||||
|  | 			$look_type = $_POST['look_type']; | ||||||
|  | 			verify_number($look_type, 'Look type', 11); | ||||||
|  | 			if ($hasLookAddons) { | ||||||
|  | 				$look_addons = $_POST['look_addons']; | ||||||
|  | 				verify_number($look_addons, 'Look addons', 11); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// pos | ||||||
|  | 			$pos_x = $_POST['pos_x']; | ||||||
|  | 			verify_number($pos_x, 'Position x', 11); | ||||||
|  | 			$pos_y = $_POST['pos_y']; | ||||||
|  | 			verify_number($pos_y, 'Position y', 11); | ||||||
|  | 			$pos_z = $_POST['pos_z']; | ||||||
|  | 			verify_number($pos_z, 'Position z', 11); | ||||||
|  |  | ||||||
|  | 			$soul = $_POST['soul']; | ||||||
|  | 			verify_number($soul, 'Soul', 10); | ||||||
|  |  | ||||||
|  | 			$town = $_POST['town']; | ||||||
|  | 			verify_number($town, 'Town', 11); | ||||||
|  |  | ||||||
|  | 			$capacity = $_POST['capacity']; | ||||||
|  | 			verify_number($capacity, 'Capacity', 11); | ||||||
|  | 			$sex = $_POST['sex']; | ||||||
|  | 			verify_number($sex, 'Sex', 1); | ||||||
|  |  | ||||||
|  | 			$lastlogin = strtotime($_POST['lastlogin']); | ||||||
|  | 			verify_number($lastlogin, 'Last login', 20); | ||||||
|  | 			$lastlogout = strtotime($_POST['lastlogout']); | ||||||
|  | 			verify_number($lastlogout, 'Last logout', 20); | ||||||
|  |  | ||||||
|  | 			$skull = $_POST['skull']; | ||||||
|  | 			verify_number($skull, 'Skull', 1); | ||||||
|  | 			$skull_time = $_POST['skull_time']; | ||||||
|  | 			verify_number($skull_time, 'Skull time', 11); | ||||||
|  |  | ||||||
|  | 			if ($db->hasColumn('players', 'loss_experience')) { | ||||||
|  | 				$loss_experience = $_POST['loss_experience']; | ||||||
|  | 				verify_number($loss_experience, 'Loss experience', 11); | ||||||
|  | 				$loss_mana = $_POST['loss_mana']; | ||||||
|  | 				verify_number($loss_mana, 'Loss mana', 11); | ||||||
|  | 				$loss_skills = $_POST['loss_skills']; | ||||||
|  | 				verify_number($loss_skills, 'Loss skills', 11); | ||||||
|  | 				$loss_containers = $_POST['loss_containers']; | ||||||
|  | 				verify_number($loss_containers, 'Loss loss_containers', 11); | ||||||
|  | 				$loss_items = $_POST['loss_items']; | ||||||
|  | 				verify_number($loss_items, 'Loss items', 11); | ||||||
|  | 			} | ||||||
|  | 			if ($db->hasColumn('players', 'offlinetraining_time')) { | ||||||
|  | 				$offlinetraining = $_POST['offlinetraining']; | ||||||
|  | 				verify_number($offlinetraining, 'Offline Training time', 11); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if ($hasBlessingsColumn) { | ||||||
|  | 				$blessings = $_POST['blessings']; | ||||||
|  | 				verify_number($blessings, 'Blessings', 3); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			$balance = $_POST['balance']; | ||||||
|  | 			verify_number($balance, 'Balance', 20); | ||||||
|  | 			if ($db->hasColumn('players', 'stamina')) { | ||||||
|  | 				$stamina = $_POST['stamina']; | ||||||
|  | 				verify_number($stamina, 'Stamina', 20); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			$deleted = (isset($_POST['deleted']) && $_POST['deleted'] == 'true'); | ||||||
|  | 			$hide = (isset($_POST['hide']) && $_POST['hide'] == 'true'); | ||||||
|  |  | ||||||
|  | 			$created = strtotime($_POST['created']); | ||||||
|  | 			verify_number($created, 'Created', 11); | ||||||
|  |  | ||||||
|  | 			$comment = isset($_POST['comment']) ? htmlspecialchars(stripslashes(substr($_POST['comment'], 0, 2000))) : NULL; | ||||||
|  |  | ||||||
|  | 			foreach ($_POST['skills'] as $skill => $value) | ||||||
|  | 				verify_number($value, $skills[$skill][0], 10); | ||||||
|  | 			foreach ($_POST['skills_tries'] as $skill => $value) | ||||||
|  | 				verify_number($value, $skills[$skill][0] . ' tries', 10); | ||||||
|  |  | ||||||
|  | 			if ($hasBlessingColumn) { | ||||||
|  | 				$bless_count = $_POST['blesscount']; | ||||||
|  | 				for ($i = 1; $i <= $bless_count; $i++) { | ||||||
|  | 					$a = 'blessing' . $i; | ||||||
|  | 					${'blessing' . $i} = (isset($_POST[$a]) && $_POST[$a] == 'true'); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (!$error) { | ||||||
|  | 				$player->setName($name); | ||||||
|  | 				$player->setAccount($account_db); | ||||||
|  | 				$player->setGroup($groups->getGroup($group)); | ||||||
|  | 				$player->setLevel($level); | ||||||
|  | 				$player->setExperience($experience); | ||||||
|  | 				$player->setVocation($vocation); | ||||||
|  | 				$player->setHealth($health); | ||||||
|  | 				$player->setHealthMax($health_max); | ||||||
|  | 				$player->setMagLevel($magic_level); | ||||||
|  | 				$player->setMana($mana); | ||||||
|  | 				$player->setManaMax($mana_max); | ||||||
|  | 				$player->setManaSpent($mana_spent); | ||||||
|  | 				$player->setLookBody($look_body); | ||||||
|  | 				$player->setLookFeet($look_feet); | ||||||
|  | 				$player->setLookHead($look_head); | ||||||
|  | 				$player->setLookLegs($look_legs); | ||||||
|  | 				$player->setLookType($look_type); | ||||||
|  | 				if ($hasLookAddons) | ||||||
|  | 					$player->setLookAddons($look_addons); | ||||||
|  | 				if ($db->hasColumn('players', 'offlinetraining_time')) | ||||||
|  | 					$player->setCustomField('offlinetraining_time', $offlinetraining); | ||||||
|  | 				$player->setPosX($pos_x); | ||||||
|  | 				$player->setPosY($pos_y); | ||||||
|  | 				$player->setPosZ($pos_z); | ||||||
|  | 				$player->setSoul($soul); | ||||||
|  | 				$player->setTownId($town); | ||||||
|  | 				$player->setCap($capacity); | ||||||
|  | 				$player->setSex($sex); | ||||||
|  | 				$player->setLastLogin($lastlogin); | ||||||
|  | 				$player->setLastLogout($lastlogout); | ||||||
|  | 				//$player->setLastIP(ip2long($lastip)); | ||||||
|  | 				$player->setSkull($skull); | ||||||
|  | 				$player->setSkullTime($skull_time); | ||||||
|  | 				if ($db->hasColumn('players', 'loss_experience')) { | ||||||
|  | 					$player->setLossExperience($loss_experience); | ||||||
|  | 					$player->setLossMana($loss_mana); | ||||||
|  | 					$player->setLossSkills($loss_skills); | ||||||
|  | 					$player->setLossContainers($loss_containers); | ||||||
|  | 					$player->setLossItems($loss_items); | ||||||
|  | 				} | ||||||
|  | 				if ($hasBlessingsColumn) | ||||||
|  | 					$player->setBlessings($blessings); | ||||||
|  |  | ||||||
|  | 				if ($hasBlessingColumn) { | ||||||
|  | 					for ($i = 1; $i <= $bless_count; $i++) { | ||||||
|  | 						$a = 'blessing' . $i; | ||||||
|  | 						$player->setCustomField('blessings' . $i, ${'blessing' . $i} ? '1' : '0'); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				$player->setBalance($balance); | ||||||
|  | 				if ($db->hasColumn('players', 'stamina')) | ||||||
|  | 					$player->setStamina($stamina); | ||||||
|  | 				if ($db->hasColumn('players', 'deletion')) | ||||||
|  | 					$player->setCustomField('deletion', $deleted ? '1' : '0'); | ||||||
|  | 				else | ||||||
|  | 					$player->setCustomField('deleted', $deleted ? '1' : '0'); | ||||||
|  | 				$player->setCustomField('hide', $hide ? '1' : '0'); | ||||||
|  | 				$player->setCustomField('created', $created); | ||||||
|  | 				if (isset($comment)) | ||||||
|  | 					$player->setCustomField('comment', $comment); | ||||||
|  |  | ||||||
|  | 				foreach ($_POST['skills'] as $skill => $value) { | ||||||
|  | 					$player->setSkill($skill, $value); | ||||||
|  | 				} | ||||||
|  | 				foreach ($_POST['skills_tries'] as $skill => $value) { | ||||||
|  | 					$player->setSkillTries($skill, $value); | ||||||
|  | 				} | ||||||
|  | 				$player->save(); | ||||||
|  | 				echo_success('Player saved at: ' . date('G:i')); | ||||||
|  | 				$player->load($id); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} else if ($id == 0) { | ||||||
|  | 		$players_db = Player::orderBy('id')->get(['id','name', 'level']); | ||||||
|  | 		?> | ||||||
|  | 		<div class="col-12 col-sm-12 col-lg-10"> | ||||||
|  | 			<div class="card card-info card-outline"> | ||||||
|  | 				<div class="card-header"> | ||||||
|  | 					<h5 class="m-0">Players</h5> | ||||||
|  | 				</div> | ||||||
|  | 				<div class="card-body"> | ||||||
|  | 					<table class="player_datatable table table-striped table-bordered table-responsive d-md-table"> | ||||||
|  | 						<thead> | ||||||
|  | 						<tr> | ||||||
|  | 							<th>ID</th> | ||||||
|  | 							<th>Name</th> | ||||||
|  | 							<th>Level</th> | ||||||
|  | 							<th style="width: 40px">Edit</th> | ||||||
|  | 						</tr> | ||||||
|  | 						</thead> | ||||||
|  | 						<tbody> | ||||||
|  | 						<?php foreach ($players_db as $player_db): ?> | ||||||
|  | 							<tr> | ||||||
|  | 								<th><?php echo $player_db->id; ?></th> | ||||||
|  | 								<td><?php echo $player_db->name; ?></a></td> | ||||||
|  | 								<td><?php echo $player_db->level; ?></a></td> | ||||||
|  |  | ||||||
|  | 								<td><a href="?p=players&id=<?php echo $player_db->id; ?>" class="btn btn-success btn-sm" title="Edit"> | ||||||
|  | 										<i class="fas fa-pencil-alt"></i> | ||||||
|  | 									</a> | ||||||
|  | 								</td> | ||||||
|  | 							</tr> | ||||||
|  | 						<?php endforeach; ?> | ||||||
|  | 						</tbody> | ||||||
|  | 					</table> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	<?php } ?> | ||||||
|  |  | ||||||
|  | 	<?php | ||||||
|  | 	if (isset($player) && $player->isLoaded()) { | ||||||
|  | 		$account = $player->getAccount(); | ||||||
|  | 		?> | ||||||
|  | 		<div class="col-12 col-sm-12 col-lg-10"> | ||||||
|  | 			<div class="card card-primary card-outline card-outline-tabs"> | ||||||
|  | 				<div class="card-header p-0 border-bottom-0"> | ||||||
|  | 					<ul class="nav nav-tabs" id="tabs-tab" role="tablist"> | ||||||
|  | 						<li class="nav-item"> | ||||||
|  | 							<a class="nav-link active" id="tabs-home-tab" data-toggle="pill" href="#tabs-home">Player</a> | ||||||
|  | 						</li> | ||||||
|  | 						<li class="nav-item"> | ||||||
|  | 							<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-stats">Stats</a> | ||||||
|  | 						</li> | ||||||
|  | 						<li class="nav-item"> | ||||||
|  | 							<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-skills">Skills</a> | ||||||
|  | 						</li> | ||||||
|  | 						<li class="nav-item"> | ||||||
|  | 							<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-pos">Pos/Look</a> | ||||||
|  | 						</li> | ||||||
|  | 						<li class="nav-item"> | ||||||
|  | 							<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-misc">Misc</a> | ||||||
|  | 						</li> | ||||||
|  | 						<li class="nav-item"> | ||||||
|  | 							<a class="nav-link" id="tabs-posts-tab" data-toggle="pill" href="#tabs-posts">Posts</a> | ||||||
|  | 						</li> | ||||||
|  | 						<li class="nav-item"> | ||||||
|  | 							<a class="nav-link" id="tabs-chars-tab" data-toggle="pill" href="#tabs-chars">Characters</a> | ||||||
|  | 						</li> | ||||||
|  | 					</ul> | ||||||
|  | 				</div> | ||||||
|  | 				<form action="<?php echo $player_base . ($id > 0 ? '&id=' . $id : ''); ?>" method="post"> | ||||||
|  | 					<?php csrf(); ?> | ||||||
|  | 					<div class="card-body"> | ||||||
|  | 						<div class="tab-content" id="tabs-tabContent"> | ||||||
|  | 							<div class="tab-pane fade active show" id="tabs-home"> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="name" class="control-label">Name</label> | ||||||
|  | 										<input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $player->getName(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="account_id">Account id:</label> | ||||||
|  | 										<input type="text" class="form-control" id="account_id" name="account_id" autocomplete="off" size="8" maxlength="11" value="<?php echo $account->getId(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="group">Group:</label> | ||||||
|  | 										<select name="group" id="group" class="form-control custom-select"> | ||||||
|  | 											<?php foreach ($groups->getGroups() as $_id => $group): ?> | ||||||
|  | 												<option value="<?php echo $_id; ?>" <?php echo($player->getGroup()->getId() == $_id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option> | ||||||
|  | 											<?php endforeach; ?> | ||||||
|  | 										</select> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="vocation">Vocation</label> | ||||||
|  | 										<select name="vocation" id="vocation" class="form-control custom-select"> | ||||||
|  | 											<?php | ||||||
|  | 											foreach ($config['vocations'] as $_id => $name) { | ||||||
|  | 												echo '<option value=' . $_id . ($_id == $player->getVocation() ? ' selected' : '') . '>' . $name . '</option>'; | ||||||
|  | 											} | ||||||
|  | 											?> | ||||||
|  | 										</select> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="sex">Sex:</label> | ||||||
|  | 										<select name="sex" id="sex" class="form-control custom-select">> | ||||||
|  | 											<?php foreach ($config['genders'] as $_id => $sex): ?> | ||||||
|  | 												<option value="<?php echo $_id; ?>" <?php echo($player->getSex() == $_id ? 'selected' : ''); ?>><?php echo strtolower($sex); ?></option> | ||||||
|  | 											<?php endforeach; ?> | ||||||
|  | 										</select> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="town">Town:</label> | ||||||
|  | 										<select name="town" id="town" class="form-control"> | ||||||
|  | 											<?php | ||||||
|  | 											$configTowns = config('towns'); | ||||||
|  | 											if (!isset($configTowns[$player->getTownId()])) { | ||||||
|  | 												$configTowns[$player->getTownId()] = 'Unknown Town'; | ||||||
|  | 											} | ||||||
|  |  | ||||||
|  | 											foreach ($configTowns as $_id => $town): ?> | ||||||
|  | 												<option value="<?php echo $_id; ?>" <?php echo($player->getTownId() == $_id ? 'selected' : ''); ?>><?php echo $town; ?></option> | ||||||
|  | 											<?php endforeach; ?> | ||||||
|  | 										</select> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="skull">Skull:</label> | ||||||
|  | 										<select name="skull" id="skull" class="form-control custom-select"> | ||||||
|  | 											<?php | ||||||
|  |  | ||||||
|  | 											foreach ($skull_type as $_id => $s_name) { | ||||||
|  | 												echo '<option value=' . $_id . ($_id == $player->getSkull() ? ' selected' : '') . '>' . $s_name . '</option>'; | ||||||
|  | 											} | ||||||
|  | 											?> | ||||||
|  | 										</select> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="skull_time">Skull time:</label> | ||||||
|  | 										<input type="text" class="form-control" id="skull_time" name="skull_time" | ||||||
|  | 											   autocomplete="off" maxlength="11" | ||||||
|  | 											   value="<?php echo $player->getSkullTime(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<?php if ($hasBlessingColumn): | ||||||
|  | 										$bless_count = $player->countBlessings(); | ||||||
|  | 										$bless = $player->checkBlessings($bless_count); ?> | ||||||
|  | 										<input type="hidden" name="blesscount" value="<?php echo $bless_count; ?>"/> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label>Blessings:</label><br/> | ||||||
|  | 											<?php for ($i = 1; $i <= $bless_count; $i++): ?> | ||||||
|  | 												<label><input class="" type="checkbox" name="blessing<?php echo $i; ?>" id="blessing<?php echo $i; ?>" value="true"<?php echo(($bless[$i - 1] == 1) ? ' checked' : '') ?>/><?php echo $i; ?></label> | ||||||
|  | 											<?php endfor ?> | ||||||
|  | 										</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 									<?php if ($hasBlessingsColumn): ?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="blessings">Blessings:</label> | ||||||
|  | 											<input type="text" class="form-control" id="blessings" name="blessings" autocomplete="off" maxlength="11" value="<?php echo $player->getBlessings(); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="balance" class="control-label">Bank Balance:</label> | ||||||
|  | 										<input type="text" class="form-control" id="balance" name="balance" autocomplete="off" maxlength="20" value="<?php echo $player->getBalance(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<div class="custom-control custom-switch custom-switch-on-danger"> | ||||||
|  | 											<input type="checkbox" class="custom-control-input" name="deleted" id="deleted" value="true" <?php echo($player->getCustomField($db->hasColumn('players', 'deletion') ? 'deletion' : 'deleted') == '1' ? ' checked' : ''); ?>> | ||||||
|  | 											<label class="custom-control-label" for="deleted">Deleted</label> | ||||||
|  | 										</div> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<div class="custom-control custom-switch custom-switch-on-success"> | ||||||
|  | 											<input type="checkbox" class="custom-control-input" name="hide" id="hide" value="true" <?php echo($player->isHidden() ? ' checked' : ''); ?>> | ||||||
|  | 											<label class="custom-control-label" for="hide">Hidden</label> | ||||||
|  | 										</div> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 							</div> | ||||||
|  | 							<div class="tab-pane fade" id="tabs-stats"> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="level" class="control-label">Level:</label> | ||||||
|  | 										<input type="text" class="form-control" id="level" name="level" autocomplete="off" value="<?php echo $player->getLevel(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="experience" class="control-label">Experience:</label> | ||||||
|  | 										<input type="text" class="form-control" id="experience" name="experience" autocomplete="off" value="<?php echo $player->getExperience(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="magic_level" class="control-label">Magic level:</label> | ||||||
|  | 										<input type="text" class="form-control" id="magic_level" name="magic_level" autocomplete="off" size="8" maxlength="11" value="<?php echo $player->getMagLevel(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="mana_spent" class="control-label">Mana spent:</label> | ||||||
|  | 										<input type="text" class="form-control" id="mana_spent" name="mana_spent" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getManaSpent(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="health" class="control-label">Health:</label> | ||||||
|  | 										<input type="text" class="form-control" id="health" name="health" autocomplete="off" size="5" maxlength="11" value="<?php echo $player->getHealth(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="health_max" class="control-label">Health max:</label> | ||||||
|  | 										<input type="text" class="form-control" id="health_max" name="health_max" autocomplete="off" size="5" maxlength="11" value="<?php echo $player->getHealthMax(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="mana" class="control-label">Mana:</label> | ||||||
|  | 										<input type="text" class="form-control" id="mana" name="mana" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getMana(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="mana_max" class="control-label">Mana max:</label> | ||||||
|  | 										<input type="text" class="form-control" id="mana_max" name="mana_max" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getManaMax(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="capacity" class="control-label">Capacity:</label> | ||||||
|  | 										<input type="text" class="form-control" id="capacity" name="capacity" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getCap(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="soul" class="control-label">Soul:</label> | ||||||
|  | 										<input type="text" class="form-control" id="soul" name="soul" autocomplete="off" size="3" maxlength="10" value="<?php echo $player->getSoul(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<?php if ($db->hasColumn('players', 'stamina')): ?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="stamina" class="control-label">Stamina:</label> | ||||||
|  | 											<input type="text" class="form-control" id="stamina" name="stamina" autocomplete="off" maxlength="20" value="<?php echo $player->getStamina(); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 									<?php if ($db->hasColumn('players', 'offlinetraining_time')): ?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="offlinetraining" class="control-label">Offline Training | ||||||
|  | 												Time:</label> | ||||||
|  | 											<input type="text" class="form-control" id="offlinetraining" name="offlinetraining" autocomplete="off" maxlength="11" value="<?php echo $player->getCustomField('offlinetraining_time'); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 								</div> | ||||||
|  | 							</div> | ||||||
|  | 							<div class="tab-pane fade" id="tabs-skills"> | ||||||
|  | 								<?php | ||||||
|  | 								foreach ($skills as $_id => $info) { | ||||||
|  | 									?> | ||||||
|  | 									<div class="form-group row"> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<?php echo '<label for="skills[' . $_id . ']" class="control-label">' . $info[0] . '</label> | ||||||
|  | 									<input type="text" class="form-control" id="skills[' . $_id . ']" name="skills[' . $_id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkill($_id) . '"/>'; ?> | ||||||
|  | 										</div> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<?php echo '<label for="skills_tries[' . $_id . ']" class="control-label">' . $info[0] . ' tries</label> | ||||||
|  | 									<input type="text" class="form-control" id="skills_tries[' . $_id . ']" name="skills_tries[' . $_id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkillTries($_id) . '"/>'; ?> | ||||||
|  | 										</div> | ||||||
|  | 									</div> | ||||||
|  | 								<?php } ?> | ||||||
|  | 							</div> | ||||||
|  | 							<div class="tab-pane fade" id="tabs-pos"> | ||||||
|  | 								<?php $outfit = setting('core.outfit_images_url') . '?id=' . $player->getLookType() . ($hasLookAddons ? '&addons=' . $player->getLookAddons() : '') . '&head=' . $player->getLookHead() . '&body=' . $player->getLookBody() . '&legs=' . $player->getLookLegs() . '&feet=' . $player->getLookFeet(); ?> | ||||||
|  | 								<div id="imgchar" style="width:64px;height:64px;position:absolute; top:30px; right:30px"> | ||||||
|  | 									<img id="player_outfit" style="margin-left:0;margin-top:0;width:64px;height:64px;" src="<?php echo $outfit; ?>" alt="player outfit"/> | ||||||
|  | 								</div> | ||||||
|  | 								<td>Position:</td> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-4"> | ||||||
|  | 										<label for="pos_x" class="control-label">X:</label> | ||||||
|  | 										<input type="text" class="form-control" id="pos_x" name="pos_x" autocomplete="off" maxlength="11" value="<?php echo $player->getPosX(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-4"> | ||||||
|  | 										<label for="pos_y" class="control-label">Y:</label> | ||||||
|  | 										<input type="text" class="form-control" id="pos_y" name="pos_y" autocomplete="off" maxlength="11" value="<?php echo $player->getPosY(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-4"> | ||||||
|  | 										<label for="pos_z" class="control-label">Z:</label> | ||||||
|  | 										<input type="text" class="form-control" id="pos_z" name="pos_z" autocomplete="off" maxlength="11" value="<?php echo $player->getPosZ(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<td>Look:</td> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-3"> | ||||||
|  | 										<label for="look_head" class="control-label">Head: <span id="look_head_val" class="font-weight-bold text-primary"></span></label> | ||||||
|  | 										<input class="custom-range" type="range" min="0" max="132" id="look_head" name="look_head" value="<?php echo $player->getLookHead(); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-3"> | ||||||
|  | 										<label for="look_body" class="control-label">Body: <span id="look_body_val" class="font-weight-bold text-primary"></span></label> | ||||||
|  | 										<input type="range" min="0" max="132" | ||||||
|  | 											   value="<?php echo $player->getLookBody(); ?>" | ||||||
|  | 											   class="custom-range" id="look_body" name="look_body"> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-3"> | ||||||
|  | 										<label for="look_legs" class="control-label">Legs: <span id="look_legs_val" class="font-weight-bold text-primary"></span></label> | ||||||
|  | 										<input type="range" min="0" max="132" | ||||||
|  | 											   value="<?php echo $player->getLookLegs(); ?>" | ||||||
|  | 											   class="custom-range" id="look_legs" name="look_legs"> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-3"> | ||||||
|  | 										<label for="look_feet" class="control-label">Feet: <span id="look_feet_val" class="font-weight-bold text-primary"></span></label> | ||||||
|  | 										<input type="range" min="0" max="132" | ||||||
|  | 											   value="<?php echo $player->getLookBody(); ?>" | ||||||
|  | 											   class="custom-range" id="look_feet" name="look_feet"> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="look_type" class="control-label">Type:</label> | ||||||
|  | 										<?php | ||||||
|  | 										$outfitlist = null; | ||||||
|  | 										$outfitlist = Outfits_loadfromXML(); | ||||||
|  | 										if ($outfitlist) { ?> | ||||||
|  | 											<select name="look_type" id="look_type" class="form-control custom-select"> | ||||||
|  | 												<?php | ||||||
|  | 												foreach ($outfitlist as $_id => $outfit) { | ||||||
|  | 													if ($outfit['enabled'] == 'yes') ; | ||||||
|  | 													echo '<option value=' . $outfit['id'] . ($outfit['id'] == $player->getLookType() ? ' selected' : '') . '>' . $outfit['name'] . ' - ' . ($outfit['type'] == 1 ? 'Male' : 'Female') . '</option>'; | ||||||
|  | 												} | ||||||
|  | 												?> | ||||||
|  | 											</select> | ||||||
|  | 										<?php } else { ?> | ||||||
|  | 											<input type="text" class="form-control" id="look_type" name="look_type" autocomplete="off" maxlength="11" value="<?php echo $player->getLookType(); ?>"/> | ||||||
|  | 										<?php } ?> | ||||||
|  | 									</div> | ||||||
|  | 									<?php if ($hasLookAddons): ?> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="look_addons" class="control-label">Addons:</label> | ||||||
|  | 											<select name="look_addons" id="look_addons" class="form-control custom-select"> | ||||||
|  | 												<?php | ||||||
|  | 												$addon_type = array("None", "First", "Second", "Both"); | ||||||
|  | 												foreach ($addon_type as $_id => $s_name) { | ||||||
|  | 													echo '<option value=' . $_id . ($_id == $player->getLookAddons() ? ' selected' : '') . '>' . $s_name . '</option>'; | ||||||
|  | 												} | ||||||
|  | 												?> | ||||||
|  | 											</select> | ||||||
|  | 										</div> | ||||||
|  | 									<?php endif; ?> | ||||||
|  | 								</div> | ||||||
|  | 							</div> | ||||||
|  | 							<div class="tab-pane fade" id="tabs-misc"> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="created" class="control-label">Created:</label> | ||||||
|  | 										<input type="text" class="form-control" id="created" name="created" | ||||||
|  | 											   autocomplete="off" | ||||||
|  | 											   maxlength="10" | ||||||
|  | 											   value="<?php echo date("M d Y, H:i:s", $player->getCustomField('created')); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="lastlogin" class="control-label">Last login:</label> | ||||||
|  | 										<input type="text" class="form-control" id="lastlogin" name="lastlogin" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $player->getLastLogin()); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="lastlogout" class="control-label">Last logout:</label> | ||||||
|  | 										<input type="text" class="form-control" id="lastlogout" name="lastlogout" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $player->getLastLogout()); ?>"/> | ||||||
|  | 									</div> | ||||||
|  | 									<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 										<label for="lastip" class="control-label">Last IP:</label> | ||||||
|  | 										<input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php | ||||||
|  | 										$lastIPColumnInfo = $db->getColumnInfo('players', 'lastip'); | ||||||
|  | 										if ($lastIPColumnInfo && is_array($lastIPColumnInfo)) { | ||||||
|  | 											if (str_contains($lastIPColumnInfo['type'], 'varbinary')) { | ||||||
|  | 												echo inet_ntop($player->getLastIP()); | ||||||
|  | 											} | ||||||
|  | 											else { | ||||||
|  | 												echo longToIp($player->getLastIP()); | ||||||
|  | 											} | ||||||
|  | 										} | ||||||
|  | 										else { | ||||||
|  | 											echo 'Error'; | ||||||
|  | 										} | ||||||
|  | 										?>" readonly/> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 								<?php if ($db->hasColumn('players', 'loss_experience')): ?> | ||||||
|  | 									<div class="form-group row"> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="loss_experience" class="control-label">Experience | ||||||
|  | 												Loss:</label> | ||||||
|  | 											<input type="text" class="form-control" id="loss_experience" name="loss_experience" autocomplete="off" maxlength="11" value="<?php echo $player->getLossExperience(); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="loss_mana" class="control-label">Mana Loss:</label> | ||||||
|  | 											<input type="text" class="form-control" id="loss_mana" name="loss_mana" autocomplete="off" maxlength="11" value="<?php echo $player->getLossMana(); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="loss_skills" class="control-label">Skills Loss:</label> | ||||||
|  | 											<input type="text" class="form-control" id="loss_skills" name="loss_skills" autocomplete="off" maxlength="11" value="<?php echo $player->getLossSkills(); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="loss_containers" class="control-label">Containers Loss:</label> | ||||||
|  | 											<input type="text" class="form-control" id="loss_containers" name="loss_containers" autocomplete="off" maxlength="11" value="<?php echo $player->getLossContainers(); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 										<div class="col-12 col-sm-12 col-lg-6"> | ||||||
|  | 											<label for="loss_items" class="control-label">Items Loss:</label> | ||||||
|  | 											<input type="text" class="form-control" id="loss_items" name="loss_items" autocomplete="off" maxlength="11" value="<?php echo $player->getLossItems(); ?>"/> | ||||||
|  | 										</div> | ||||||
|  | 									</div> | ||||||
|  | 								<?php endif; ?> | ||||||
|  | 								<div class="form-group row"> | ||||||
|  | 									<div class="col-12"> | ||||||
|  | 										<label for="comment" class="control-label">Comment:</label> | ||||||
|  | 										<textarea class="form-control" id="comment" name="comment" rows="10" cols="50" wrap="virtual"><?php echo $player->getCustomField("comment"); ?></textarea> | ||||||
|  | 										<small>[max. length: 2000 chars, 50 lines (ENTERs)]</small> | ||||||
|  | 									</div> | ||||||
|  | 								</div> | ||||||
|  | 							</div> | ||||||
|  | 							<div class="tab-pane fade" id="tabs-posts"> | ||||||
|  | 								<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||||
|  | 									<thead> | ||||||
|  | 									<tr> | ||||||
|  | 										<th class="w-25">Topic</th> | ||||||
|  | 										<th>Content</th> | ||||||
|  | 									</tr> | ||||||
|  | 									</thead> | ||||||
|  | 									<tbody> | ||||||
|  | 									<?php | ||||||
|  | 									$posts = $db->query('SELECT `author_guid`,`section`,`first_post`,`post_text`,`post_date`, `post_topic`,`post_html`,`post_smile`,`' . TABLE_PREFIX . 'forum_boards`.`name` AS `forum_Name` FROM `' . | ||||||
|  | 										TABLE_PREFIX . 'forum` LEFT JOIN `' . TABLE_PREFIX . 'forum_boards` ON `' . | ||||||
|  | 										TABLE_PREFIX . 'forum`.section = `' . TABLE_PREFIX . 'forum_boards`.id WHERE `author_guid` = "' . $player->getId() . '" ORDER BY `post_date` DESC LIMIT 10'); | ||||||
|  | 									if ($posts->rowCount() > 0) { | ||||||
|  | 										$posts = $posts->fetchAll(); | ||||||
|  | 										foreach ($posts as $post) { | ||||||
|  | 											$text = ($post['post_html'] > 0 ? $post['post_text'] : htmlspecialchars($post['post_text'])); | ||||||
|  | 											$post['content'] = ($post['post_html'] > 0 ? $text : Forum::parseBBCode(nl2br($text), $post['post_smile'] == 0)); | ||||||
|  | 											?> | ||||||
|  | 											<tr> | ||||||
|  | 												<th><?php echo htmlspecialchars($post['post_topic']); ?><br/><small><?php echo date('d M y H:i:s', $post['post_date']); ?></small><br/> | ||||||
|  | 													Topic: <a href="<?php echo getForumThreadLink($post['first_post']); ?>" class="link-black text-sm"><i class="fa fa-share margin-r-5"></i> Link</a><br/> | ||||||
|  | 													Forum: <a href="<?php echo getForumBoardLink($post['section']); ?>" class="link-black text-sm"><i class="fa fa-share margin-r-5"></i> <?php echo $post['forum_Name']; ?></a></th> | ||||||
|  | 												<th><?php echo $post['content']; ?></th> | ||||||
|  | 											</tr> | ||||||
|  | 											<?php | ||||||
|  | 										} | ||||||
|  | 										unset($post); | ||||||
|  | 									} else { | ||||||
|  | 										echo '<tr><td colspan="2">This user has no posts</td></tr>'; | ||||||
|  | 									}; ?> | ||||||
|  | 									</tbody> | ||||||
|  | 								</table> | ||||||
|  | 							</div> | ||||||
|  | 							<div class="tab-pane fade" id="tabs-chars"> | ||||||
|  | 								<div class="row"> | ||||||
|  | 									<?php | ||||||
|  | 									if (isset($account) && $account->isLoaded()) { | ||||||
|  | 										$account_players = Player::where('account_id', $account->getId())->orderBy('id')->get(); | ||||||
|  | 										if (isset($account_players)) { ?> | ||||||
|  | 											<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||||
|  | 												<thead> | ||||||
|  | 												<tr> | ||||||
|  | 													<th>#</th> | ||||||
|  | 													<th>Name</th> | ||||||
|  | 													<th>Level</th> | ||||||
|  | 													<th>Vocation</th> | ||||||
|  | 													<th style="width: 40px">Edit</th> | ||||||
|  | 												</tr> | ||||||
|  | 												</thead> | ||||||
|  | 												<tbody> | ||||||
|  | 												<?php foreach ($account_players as $i => $player): ?> | ||||||
|  | 													<tr> | ||||||
|  | 														<th><?php echo $i + 1; ?></th> | ||||||
|  | 														<td><?php echo $player->name; ?></td> | ||||||
|  | 														<td><?php echo $player->level; ?></td> | ||||||
|  | 														<td><?php echo $player->vocation_name; ?></td> | ||||||
|  | 														<td><a href="?p=players&id=<?php echo $player->getKey() ?>" class=" btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></a></td> | ||||||
|  | 													</tr> | ||||||
|  | 												<?php endforeach ?> | ||||||
|  | 												</tbody> | ||||||
|  | 											</table> | ||||||
|  | 											<?php | ||||||
|  | 										} | ||||||
|  | 									} ?> | ||||||
|  | 								</div> | ||||||
|  | 							</div> | ||||||
|  | 						</div> | ||||||
|  | 					</div> | ||||||
|  | 					<div class="card-footer text-center"> | ||||||
|  | 						<input type="hidden" name="save" value="yes"/> | ||||||
|  | 						<button type="submit" class="btn btn-info float-left"><i class="fas fa-update"></i> Update</button> | ||||||
|  | 						<a href="<?php echo ADMIN_URL; ?>?p=accounts&id=<?php echo $account->getId(); ?>" class="btn btn-secondary">Edit Account</a> | ||||||
|  | 						<a href="<?php echo ADMIN_URL; ?>?p=players" class="btn btn-danger float-right"><i class="fas fa-cancel"></i> Cancel</a> | ||||||
|  | 					</div> | ||||||
|  | 				</form> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  |  | ||||||
|  | 		<script type="text/javascript"> | ||||||
|  | 			$('#lastlogin').datetimepicker({format: "M d Y, H:i:s",}); | ||||||
|  | 			$('#lastlogout').datetimepicker({format: "M d Y, H:i:s",}); | ||||||
|  | 			$('#created').datetimepicker({format: "M d Y, H:i:s",}); | ||||||
|  |  | ||||||
|  | 			$(document).ready(function () { | ||||||
|  | 				const $headSpan = $('#look_head_val'); | ||||||
|  | 				const $headvalue = $('#look_head'); | ||||||
|  | 				$headSpan.html($headvalue.val()); | ||||||
|  | 				$headvalue.on('input', () => { | ||||||
|  | 					$headSpan.html($headvalue.val()); | ||||||
|  | 				}); | ||||||
|  | 				$headvalue.on('change', () => { | ||||||
|  | 					updateOutfit(); | ||||||
|  | 				}); | ||||||
|  |  | ||||||
|  | 				const $bodySpan = $('#look_body_val'); | ||||||
|  | 				const $bodyvalue = $('#look_body'); | ||||||
|  | 				$bodySpan.html($bodyvalue.val()); | ||||||
|  | 				$bodyvalue.on('input', () => { | ||||||
|  | 					$bodySpan.html($bodyvalue.val()); | ||||||
|  | 				}); | ||||||
|  | 				$bodyvalue.on('change', () => { | ||||||
|  | 					updateOutfit(); | ||||||
|  | 				}); | ||||||
|  |  | ||||||
|  | 				const $legsSpan = $('#look_legs_val'); | ||||||
|  | 				const $legsvalue = $('#look_legs'); | ||||||
|  | 				$legsSpan.html($legsvalue.val()); | ||||||
|  | 				$legsvalue.on('input', () => { | ||||||
|  | 					$legsSpan.html($legsvalue.val()); | ||||||
|  | 				}); | ||||||
|  | 				$legsvalue.on('change', () => { | ||||||
|  | 					updateOutfit(); | ||||||
|  | 				}); | ||||||
|  |  | ||||||
|  | 				const $feetSpan = $('#look_feet_val'); | ||||||
|  | 				const $feetvalue = $('#look_feet'); | ||||||
|  | 				$feetSpan.html($feetvalue.val()); | ||||||
|  | 				$feetvalue.on('input', () => { | ||||||
|  | 					$feetSpan.html($feetvalue.val()); | ||||||
|  | 				}); | ||||||
|  | 				$feetvalue.on('change', () => { | ||||||
|  | 					updateOutfit(); | ||||||
|  | 				}); | ||||||
|  |  | ||||||
|  | 				const $lookvalue = $('#look_type'); | ||||||
|  | 				$lookvalue.on('change', () => { | ||||||
|  | 					updateOutfit(); | ||||||
|  | 				}); | ||||||
|  |  | ||||||
|  | 				<?php if($hasLookAddons): ?> | ||||||
|  | 				const $addonvalue = $('#look_addons'); | ||||||
|  | 				$addonvalue.on('change', () => { | ||||||
|  | 					updateOutfit(); | ||||||
|  | 				}); | ||||||
|  | 				<?php endif; ?> | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  | 			function updateOutfit() { | ||||||
|  | 				const look_head = $('#look_head').val(); | ||||||
|  | 				const look_body = $('#look_body').val(); | ||||||
|  | 				const look_legs = $('#look_legs').val(); | ||||||
|  | 				const look_feet = $('#look_feet').val(); | ||||||
|  | 				const look_type = $('#look_type').val(); | ||||||
|  |  | ||||||
|  | 				let look_addons = ''; | ||||||
|  | 				<?php if($hasLookAddons): ?> | ||||||
|  | 				look_addons = '&addons=' + $('#look_addons').val(); | ||||||
|  | 				<?php endif; ?> | ||||||
|  | 				$("#player_outfit").attr("src", '<?= setting('core.outfit_images_url'); ?>?id=' + look_type + look_addons + '&head=' + look_head + '&body=' + look_body + '&legs=' + look_legs + '&feet=' + look_feet); | ||||||
|  | 			} | ||||||
|  | 		</script> | ||||||
|  | 	<?php } ?> | ||||||
|  | 	<div class="col-12 col-sm-12 col-lg-2"> | ||||||
|  | 		<div class="card card-info card-outline"> | ||||||
|  | 			<div class="card-header"> | ||||||
|  | 				<h5 class="m-0">Search Player</h5> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="card-body row"> | ||||||
|  | 				<div class="col-6 col-lg-12"> | ||||||
|  | 					<form action="<?php echo $player_base; ?>" method="post"> | ||||||
|  | 						<?php csrf(); ?> | ||||||
|  | 						<label for="search">Player Name:</label> | ||||||
|  | 						<div class="input-group input-group-sm"> | ||||||
|  | 							<input type="text" class="form-control" id="search" name="search" value="<?= escapeHtml($search_player); ?>" maxlength="32" size="32"> | ||||||
|  | 							<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span> | ||||||
|  | 						</div> | ||||||
|  | 					</form> | ||||||
|  | 				</div> | ||||||
|  | 				<div class="col-6 col-lg-12"> | ||||||
|  | 					<form action="<?php echo $player_base; ?>" method="post"> | ||||||
|  | 						<?php csrf(); ?> | ||||||
|  | 						<label for="id">Player ID:</label> | ||||||
|  | 						<div class="input-group input-group-sm"> | ||||||
|  | 							<input type="text" class="form-control" id="id" name="id" value="<?= $id; ?>" maxlength="32" size="32"> | ||||||
|  | 							<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span> | ||||||
|  | 						</div> | ||||||
|  | 					</form> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | 	$(function () { | ||||||
|  | 		$('.player_datatable').DataTable({ | ||||||
|  | 			"order": [[0, "asc"]] | ||||||
|  | 		}); | ||||||
|  | 	}); | ||||||
|  | </script> | ||||||
							
								
								
									
										196
									
								
								admin/pages/plugins.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,196 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Plugins | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Plugins; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Plugin manager'; | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | $use_datatable = true; | ||||||
|  |  | ||||||
|  | if (!setting('core.admin_plugins_manage_enable')) { | ||||||
|  | 	warning('Plugin installation and management is disabled in Settings.<br/>If you wish to enable, go to Settings and enable <strong>Enable Plugins Manage</strong>.'); | ||||||
|  | } | ||||||
|  | else { | ||||||
|  | 	$pluginUploadEnabled = true; | ||||||
|  | 	if(!\class_exists('\ZipArchive')) { | ||||||
|  | 		error('Please install PHP zip extension. Plugins upload disabled until then.'); | ||||||
|  | 		$pluginUploadEnabled = false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$twig->display('admin.plugins.form.html.twig', ['pluginUploadEnabled' => $pluginUploadEnabled]); | ||||||
|  |  | ||||||
|  | 	if (isset($_POST['uninstall'])) { | ||||||
|  | 		$uninstall = $_POST['uninstall']; | ||||||
|  |  | ||||||
|  | 		if (Plugins::uninstall($uninstall)) { | ||||||
|  | 			success('Successfully uninstalled plugin ' . $uninstall); | ||||||
|  | 		} else { | ||||||
|  | 			error('Error while uninstalling plugin ' . $uninstall . ': ' . Plugins::getError()); | ||||||
|  | 		} | ||||||
|  | 	} else if (isset($_POST['enable'])) { | ||||||
|  | 		$enable = $_POST['enable']; | ||||||
|  | 		if (Plugins::enable($enable)) { | ||||||
|  | 			success('Successfully enabled plugin ' . $enable); | ||||||
|  | 		} else { | ||||||
|  | 			error('Error while enabling plugin ' . $enable . ': ' . Plugins::getError()); | ||||||
|  | 		} | ||||||
|  | 	} else if (isset($_POST['disable'])) { | ||||||
|  | 		$disable = $_POST['disable']; | ||||||
|  | 		if (Plugins::disable($disable)) { | ||||||
|  | 			success('Successfully disabled plugin ' . $disable); | ||||||
|  | 		} else { | ||||||
|  | 			error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else if (isset($_GET['check-updates'])) { | ||||||
|  | 		$repoUri = $config['admin_plugins_api_uri'] ?? 'https://plugins.my-aac.org/api/'; | ||||||
|  | 		success("Fetching latest info from $repoUri.."); | ||||||
|  |  | ||||||
|  | 		$adminPlugins = new \MyAAC\Admin\Plugins(); | ||||||
|  |  | ||||||
|  | 		$adminPlugins->setApiBaseUri($repoUri); | ||||||
|  |  | ||||||
|  | 		try { | ||||||
|  | 			$plugins = $adminPlugins->getLatestVersions(); | ||||||
|  | 		} | ||||||
|  | 		catch (Exception $e) { | ||||||
|  | 			error($e->getMessage()); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (isset($plugins) && count($plugins) > 0) { | ||||||
|  | 			$outdated = []; | ||||||
|  |  | ||||||
|  | 			foreach (get_plugins(true) as $plugin) { | ||||||
|  | 				$string = file_get_contents(BASE . 'plugins/' . $plugin . '.json'); | ||||||
|  | 				$plugin_info = json_decode($string, true); | ||||||
|  |  | ||||||
|  | 				if (!$plugin_info) { | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				$disabled = (str_contains($plugin, 'disabled.')); | ||||||
|  | 				$pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin); | ||||||
|  |  | ||||||
|  | 				$info = $plugins[$pluginOriginal] ?? false; | ||||||
|  | 				if ($info && version_compare($info['version'], $plugin_info['version'], '>')) { | ||||||
|  | 					$outdated[] = [ | ||||||
|  | 						'name' => $pluginOriginal, | ||||||
|  | 						'yourVersion' => $plugin_info['version'], | ||||||
|  | 						'latestVersion' => $info['version'], | ||||||
|  | 						'link' => $info['link'] ?? 'Unknown', | ||||||
|  | 						'download_link' => $info['download_link'] ?? 'Unknown', | ||||||
|  | 					]; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (count($outdated) > 0) { | ||||||
|  | 				info('Following updates have been found for your plugins:'); | ||||||
|  | 				$twig->display('admin.plugins.outdated.html.twig', ['plugins' => $outdated]); | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				success('All plugins up to date!'); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} else if (isset($_FILES['plugin']['name'])) { | ||||||
|  | 		$file = $_FILES['plugin']; | ||||||
|  | 		$filename = $file['name']; | ||||||
|  | 		$tmp_name = $file['tmp_name']; | ||||||
|  | 		$type = $file['type']; | ||||||
|  |  | ||||||
|  | 		$name = explode('.', $filename); | ||||||
|  | 		$accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed', 'application/octet-stream', 'application/zip-compressed'); | ||||||
|  |  | ||||||
|  | 		if (isset($file['error'])) { | ||||||
|  | 			$error = 'Error uploading file'; | ||||||
|  | 			switch ($file['error']) { | ||||||
|  | 				case UPLOAD_ERR_OK: | ||||||
|  | 					$error = false; | ||||||
|  | 					break; | ||||||
|  | 				case UPLOAD_ERR_INI_SIZE: | ||||||
|  | 				case UPLOAD_ERR_FORM_SIZE: | ||||||
|  | 					$error .= ' - file too large (limit of ' . ini_get('upload_max_filesize') . ' bytes). You can enlarge the limits by changing "upload_max_filesize" in php.ini'; | ||||||
|  | 					break; | ||||||
|  | 				case UPLOAD_ERR_PARTIAL: | ||||||
|  | 					$error .= ' - file upload was not completed.'; | ||||||
|  | 					break; | ||||||
|  | 				case UPLOAD_ERR_NO_FILE: | ||||||
|  | 					$error .= ' - zero-length file uploaded.'; | ||||||
|  | 					break; | ||||||
|  | 				default: | ||||||
|  | 					$error .= ' - internal error #' . $file['error']; | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (isset($error) && $error != false) { | ||||||
|  | 			error($error); | ||||||
|  | 		} else { | ||||||
|  | 			if (is_uploaded_file($file['tmp_name'])) { | ||||||
|  | 				$filetype = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); | ||||||
|  | 				if ($filetype == 'zip') // check if it is zipped/compressed file | ||||||
|  | 				{ | ||||||
|  | 					$tmp_filename = pathinfo($filename, PATHINFO_FILENAME); | ||||||
|  | 					$targetzip = BASE . 'plugins/' . $tmp_filename . '.zip'; | ||||||
|  |  | ||||||
|  | 					if (move_uploaded_file($tmp_name, $targetzip)) { // move uploaded file | ||||||
|  | 						if (Plugins::install($targetzip)) { | ||||||
|  | 							foreach (Plugins::getWarnings() as $warning) { | ||||||
|  | 								warning($warning); | ||||||
|  | 							} | ||||||
|  |  | ||||||
|  | 							$info = Plugins::getPluginJson(); | ||||||
|  | 							success((isset($info['name']) ? '<strong>' . $info['name'] . '</strong> p' : 'P') . 'lugin has been successfully installed.'); | ||||||
|  | 						} else { | ||||||
|  | 							$error = Plugins::getError(); | ||||||
|  | 							error(!empty($error) ? $error : 'Unexpected error happened while installing plugin. Please try again later.'); | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						unlink($targetzip); // delete the Zipped file | ||||||
|  | 					} else | ||||||
|  | 						error('There was a problem with the upload. Please try again.'); | ||||||
|  | 				} else { | ||||||
|  | 					error('The file you are trying to upload is not a .zip file. Please try again.'); | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				error('Error uploading file - unknown error.'); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $plugins = array(); | ||||||
|  | foreach (get_plugins(true) as $plugin) { | ||||||
|  | 	$string = file_get_contents(BASE . 'plugins/' . $plugin . '.json'); | ||||||
|  | 	$plugin_info = json_decode($string, true); | ||||||
|  |  | ||||||
|  | 	if (!$plugin_info) { | ||||||
|  | 		warning('Cannot load plugin info ' . $plugin . '.json'); | ||||||
|  | 	} else { | ||||||
|  | 		$disabled = (str_contains($plugin, 'disabled.')); | ||||||
|  | 		$pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin); | ||||||
|  | 		$plugins[] = array( | ||||||
|  | 			'name' => $plugin_info['name'] ?? '', | ||||||
|  | 			'description' => $plugin_info['description'] ?? '', | ||||||
|  | 			'version' => $plugin_info['version'] ?? '', | ||||||
|  | 			'author' => $plugin_info['author'] ?? '', | ||||||
|  | 			'contact' => $plugin_info['contact'] ?? '', | ||||||
|  | 			'file' => $pluginOriginal, | ||||||
|  | 			'enabled' => !$disabled, | ||||||
|  | 			'uninstall' => isset($plugin_info['uninstall']) | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('admin.plugins.html.twig', array( | ||||||
|  | 	'plugins' => $plugins | ||||||
|  | )); | ||||||
							
								
								
									
										61
									
								
								admin/pages/reports.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,61 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Reports | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Lee | ||||||
|  |  * @copyright 2020 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Report Viewer'; | ||||||
|  | $use_datatable = true; | ||||||
|  |  | ||||||
|  | $files = array(); | ||||||
|  | $server_path_reports = $config['data_path'] . 'reports/'; | ||||||
|  |  | ||||||
|  | if (file_exists($server_path_reports)) { | ||||||
|  | 	foreach (scandir($server_path_reports, SCANDIR_SORT_ASCENDING) as $f) { | ||||||
|  | 		if ($f[0] === '.') { | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (is_dir($server_path_reports . $f)) { | ||||||
|  | 			foreach (scandir($server_path_reports . $f, SCANDIR_SORT_ASCENDING) as $f2) { | ||||||
|  | 				if ($f2[0] === '.') { | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				$files[] = array($f . '/' . $f2, $server_path_reports); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		$files[] = array($f, $server_path_reports); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | foreach ($files as &$f) { | ||||||
|  | 	$f['mtime'] = filemtime($f[1] . $f[0]); | ||||||
|  | 	$f['name'] = $f[0]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | unset($f); | ||||||
|  |  | ||||||
|  | $file = isset($_GET['file']) ? $_GET['file'] : NULL; | ||||||
|  | if (!empty($file)) { | ||||||
|  | 	if (!preg_match('/[^A-z0-9\' _\/\-\.]/', $file)) { | ||||||
|  | 		if (file_exists($server_path_reports . $file)) { | ||||||
|  | 			$file_content = nl2br(file_get_contents($server_path_reports . $file)); | ||||||
|  |  | ||||||
|  | 			$twig->display('admin.logs.view.html.twig', array('file' => $file, 'content' => $file_content)); | ||||||
|  | 		} else { | ||||||
|  | 			echo 'Specified file does not exist.'; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		echo 'Invalid file name specified.'; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('admin.reports.html.twig', array('files' => $files)); | ||||||
							
								
								
									
										60
									
								
								admin/pages/settings.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,60 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Menus | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Plugins; | ||||||
|  | use MyAAC\Settings; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Settings'; | ||||||
|  |  | ||||||
|  | require_once SYSTEM . 'clients.conf.php'; | ||||||
|  | if (empty($_GET['plugin'])) { | ||||||
|  | 	error('Please select plugin from left Panel.'); | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $plugin = $_GET['plugin']; | ||||||
|  |  | ||||||
|  | if($plugin != 'core') { | ||||||
|  | 	$pluginSettings = Plugins::getPluginSettings($plugin); | ||||||
|  | 	if (!$pluginSettings) { | ||||||
|  | 		error('This plugin does not exist or does not have settings defined.'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$settingsFilePath = BASE . $pluginSettings; | ||||||
|  | } | ||||||
|  | else { | ||||||
|  | 	$settingsFilePath = SYSTEM . 'settings.php'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (!file_exists($settingsFilePath)) { | ||||||
|  | 	error("Plugin $plugin does not exist or does not have settings defined."); | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $settingsFile = require $settingsFilePath; | ||||||
|  | if (!is_array($settingsFile)) { | ||||||
|  | 	error("Cannot load settings file for plugin $plugin"); | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $settingsKeyName = ($plugin == 'core' ? $plugin : $settingsFile['key']); | ||||||
|  |  | ||||||
|  | $title = ($plugin == 'core' ? 'Settings' : 'Plugin Settings - ' . $settingsFile['name']); | ||||||
|  |  | ||||||
|  | $settingsParsed = Settings::display($settingsKeyName, $settingsFile['settings']); | ||||||
|  |  | ||||||
|  | $twig->display('admin.settings.html.twig', [ | ||||||
|  | 	'settingsParsed' => $settingsParsed['content'], | ||||||
|  | 	'settings' => $settingsFile['settings'], | ||||||
|  | 	'script' => $settingsParsed['script'], | ||||||
|  | 	'settingsKeyName' => $settingsKeyName, | ||||||
|  | ]); | ||||||
							
								
								
									
										37
									
								
								admin/pages/statistics.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,37 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Statistics | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\Models\Account; | ||||||
|  | use MyAAC\Models\Guild; | ||||||
|  | use MyAAC\Models\House; | ||||||
|  | use MyAAC\Models\Player; | ||||||
|  |  | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Statistics'; | ||||||
|  |  | ||||||
|  | $total_accounts = Account::count(); | ||||||
|  | $total_players = Player::count(); | ||||||
|  | $total_guilds = Guild::count(); | ||||||
|  | $total_houses = House::count(); | ||||||
|  |  | ||||||
|  | $points = Account::select(['premium_points', (USE_ACCOUNT_NAME ? 'name' : 'id')]) | ||||||
|  | 	->orderByDesc('premium_points') | ||||||
|  | 	->limit(10) | ||||||
|  | 	->get() | ||||||
|  | 	->toArray(); | ||||||
|  |  | ||||||
|  | $twig->display('admin.statistics.html.twig', array( | ||||||
|  | 	'total_accounts' => $total_accounts, | ||||||
|  | 	'total_players' => $total_players, | ||||||
|  | 	'total_guilds' => $total_guilds, | ||||||
|  | 	'total_houses' => $total_houses, | ||||||
|  | 	'account_type' => (USE_ACCOUNT_NAME ? 'name' : 'number'), | ||||||
|  | 	'points' => $points | ||||||
|  | )); | ||||||
							
								
								
									
										33
									
								
								admin/pages/tools.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,33 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Tools | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  | $title = 'Tools'; | ||||||
|  |  | ||||||
|  | if (!isset($_GET['tool'])) { | ||||||
|  | 	echo 'Tool not set.'; | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $tool = $_GET['tool']; | ||||||
|  | if (preg_match("/[^A-z0-9_\-]/", $tool)) { | ||||||
|  | 	echo 'Invalid tool.'; | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $file = ADMIN . 'tools/' . $tool . '.php'; | ||||||
|  |  | ||||||
|  | if (@file_exists($file)) { | ||||||
|  | 	require $file; | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | echo 'Tool <strong>' . $tool . '</strong> not found.'; | ||||||
|  |  | ||||||
|  | ?> | ||||||
| @@ -4,37 +4,35 @@ | |||||||
|  * |  * | ||||||
|  * @package   MyAAC |  * @package   MyAAC | ||||||
|  * @author    Slawkens <slawkens@gmail.com> |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  * @copyright 2017 MyAAC |  * @copyright 2019 MyAAC | ||||||
|  * @link      http://my-aac.org |  * @link      https://my-aac.org | ||||||
|  */ |  */ | ||||||
| defined('MYAAC') or die('Direct access not allowed!'); | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
| $title = 'Version check'; | $title = 'Version check'; | ||||||
| 
 | 
 | ||||||
| // fetch version
 | // fetch version
 | ||||||
| //$file = @fopen('http://my-aac.org/VERSION', 'r') or die('Error while fetching version.');
 | //$file = @fopen('https://my-aac.org/VERSION', 'r') or die('Error while fetching version.');
 | ||||||
| //$myaac_version = fgets($file);
 | //$myaac_version = fgets($file);
 | ||||||
| $myaac_version = @file_get_contents('http://my-aac.org/VERSION'); | $myaac_version = @file_get_contents('https://my-aac.org/VERSION'); | ||||||
| if(!$myaac_version) { | if (!$myaac_version) { | ||||||
| 	warning('Error while fetching version info from http://my-aac.org<br/> | 	warning('Error while fetching version info from https://my-aac.org<br/> | ||||||
| 	Please try again later.'); | 	Please try again later.'); | ||||||
| 	return; | 	return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // compare them
 | // compare them
 | ||||||
| $version_compare = version_compare($myaac_version, MYAAC_VERSION); | $version_compare = version_compare($myaac_version, MYAAC_VERSION); | ||||||
| if($version_compare == 0) { | if ($version_compare == 0) { | ||||||
| 	success('MyAAC latest version is ' . $myaac_version . '. You\'re using the latest version. | 	success('MyAAC latest version is ' . $myaac_version . '. You\'re using the latest version. | ||||||
| 	<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=changelog', 'here')); | 	<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=clmd', 'here')); | ||||||
| } | } else if ($version_compare < 0) { | ||||||
| else if($version_compare < 0) { | 	success('Woah, seems you\'re using newer version as latest released one! MyAAC latest released version is ' . $myaac_version . ', and you\'re using version ' . MYAAC_VERSION . '. | ||||||
| 	echo success('Woah, seems you\'re using newer version as latest released one! MyAAC latest released version is ' . $myaac_version . ', and you\'re using version ' . MYAAC_VERSION . '. | 	<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=clmd', 'here')); | ||||||
| 	<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=changelog', 'here')); | } else { | ||||||
| } |  | ||||||
| else { |  | ||||||
| 	warning('You\'re using outdated version.<br/> | 	warning('You\'re using outdated version.<br/> | ||||||
| 		Your version: <b>' . MYAAC_VERSION . '</b><br/> | 		Your version: <b>' . MYAAC_VERSION . '</b><br/> | ||||||
| 		Latest version: <b>' . $myaac_version . '</b><br/> | 		Latest version: <b>' . $myaac_version . '</b><br/> | ||||||
| 		Download available at: <a href="http://my-aac.org" target="_blank">www.my-aac.org</a>'); | 		Download available at: <a href="https://my-aac.org" target="_blank">www.my-aac.org</a>'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* | /* | ||||||
| @@ -49,4 +47,3 @@ function version_revert($version) | |||||||
| 	$release = $version; | 	$release = $version; | ||||||
| 	return $major . '.' . $minor . '.' . $release; | 	return $major . '.' . $minor . '.' . $release; | ||||||
| }*/ | }*/ | ||||||
| ?>
 |  | ||||||
							
								
								
									
										65
									
								
								admin/pages/visitors.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,65 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Visitors viewer | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2019 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  | defined('MYAAC') or die('Direct access not allowed!'); | ||||||
|  |  | ||||||
|  | use DeviceDetector\DeviceDetector; | ||||||
|  | use DeviceDetector\Parser\Client\Browser; | ||||||
|  | use DeviceDetector\Parser\OperatingSystem; | ||||||
|  | use MyAAC\Visitors; | ||||||
|  |  | ||||||
|  | $title = 'Visitors'; | ||||||
|  | $use_datatable = true; | ||||||
|  |  | ||||||
|  | if (!setting('core.visitors_counter')): ?> | ||||||
|  | 	Visitors counter is disabled.<br/> | ||||||
|  | 	You can enable it in Settings -> General -> Visitors Counter.<br/> | ||||||
|  | 	<?php | ||||||
|  | 	return; | ||||||
|  | endif; | ||||||
|  |  | ||||||
|  | $visitors = new Visitors(setting('core.visitors_counter_ttl')); | ||||||
|  |  | ||||||
|  | function compare($a, $b): int { | ||||||
|  | 	return $a['lastvisit'] > $b['lastvisit'] ? -1 : 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $tmp = $visitors->getVisitors(); | ||||||
|  | usort($tmp, 'compare'); | ||||||
|  |  | ||||||
|  | foreach ($tmp as &$visitor) { | ||||||
|  | 	$userAgent = $visitor['user_agent'] ?? ''; | ||||||
|  | 	if (!strlen($userAgent) || $userAgent == 'unknown') { | ||||||
|  | 		$browser = 'Unknown'; | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		$dd = new DeviceDetector($userAgent); | ||||||
|  | 		$dd->parse(); | ||||||
|  |  | ||||||
|  | 		if ($dd->isBot()) { | ||||||
|  | 			$bot = $dd->getBot(); | ||||||
|  | 			$message = '(Bot) %s, <a href="%s" target="_blank">%s</a>'; | ||||||
|  | 			$browser = sprintf($message, $bot['category'] ?? 'Unknown', $bot['url'] ?? '', $bot['name'] ?? 'Unknown name'); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			$osFamily = OperatingSystem::getOsFamily($dd->getOs('name')); | ||||||
|  | 			$browserFamily = Browser::getBrowserFamily($dd->getClient('name')); | ||||||
|  |  | ||||||
|  | 			$browser = $osFamily . ', ' . $browserFamily; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$visitor['browser'] = $browser; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $twig->display('admin.visitors.html.twig', array( | ||||||
|  | 	'config_visitors_counter_ttl' => setting('core.visitors_counter_ttl'), | ||||||
|  | 	'visitors' => $tmp | ||||||
|  | )); | ||||||
|  | ?> | ||||||
							
								
								
									
										69
									
								
								admin/template/menus.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,69 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $menus = [ | ||||||
|  | 	['name' => 'Dashboard', 'icon' => 'tachometer-alt', 'order' => 10, 'link' => 'dashboard'], | ||||||
|  | 	['name' => 'Settings', 'icon' => 'edit', 'order' => 19, 'link' => | ||||||
|  | 		require ADMIN . 'includes/settings_menus.php' | ||||||
|  | 	], | ||||||
|  | 	['name' => 'News', 'icon' => 'newspaper', 'order' => 20,  'link' => | ||||||
|  | 		[ | ||||||
|  | 			['name' => 'View', 'link' => 'news', 'icon' => 'list', 'order' => 10], | ||||||
|  | 			['name' => 'Add news', 'link' => 'news&action=new&type=1', 'icon' => 'plus', 'order' => 20], | ||||||
|  | 			['name' => 'Add ticker', 'link' => 'news&action=new&type=2', 'icon' => 'plus', 'order' => 30], | ||||||
|  | 			['name' => 'Add article', 'link' => 'news&action=new&type=3', 'icon' => 'plus', 'order' => 40], | ||||||
|  | 		], | ||||||
|  | 	], | ||||||
|  | 	['name' => 'Changelogs', 'icon' => 'newspaper', 'order' => 30, 'link' => | ||||||
|  | 		[ | ||||||
|  | 			['name' => 'View', 'link' => 'changelog', 'icon' => 'list', 'order' => 10], | ||||||
|  | 			['name' => 'Add', 'link' => 'changelog&action=new', 'icon' => 'plus', 'order' => 20], | ||||||
|  | 		], | ||||||
|  | 	], | ||||||
|  | 	['name' => 'Mailer', 'icon' => 'envelope', 'order' => 40, 'link' => 'mailer', 'disabled' => !setting('core.mail_enabled')], | ||||||
|  | 	['name' => 'Pages', 'icon' => 'book', 'order' => 50, 'link' => | ||||||
|  | 		[ | ||||||
|  | 			['name' => 'View', 'link' => 'pages', 'icon' => 'list', 'order' => 10], | ||||||
|  | 			['name' => 'Add', 'link' => 'pages&action=new', 'icon' => 'plus', 'order' => 20], | ||||||
|  | 		], | ||||||
|  | 	], | ||||||
|  | 	['name' => 'Menus', 'icon' => 'list', 'order' => 60, 'link' => 'menus'], | ||||||
|  | 	['name' => 'Plugins', 'icon' => 'plug', 'order' => 70, 'link' => 'plugins'], | ||||||
|  | 	['name' => 'Server Data', 'icon' => 'gavel', 'order' => 80, 'link' => 'data'], | ||||||
|  | 	['name' => 'Editor', 'icon' => 'edit', 'order' => 90, 'link' => | ||||||
|  | 		[ | ||||||
|  | 			['name' => 'Accounts', 'link' => 'accounts', 'icon' => 'users', 'order' => 10], | ||||||
|  | 			['name' => 'Players', 'link' => 'players', 'icon' => 'user-astronaut', 'order' => 20], | ||||||
|  | 		], | ||||||
|  | 	], | ||||||
|  | 	['name' => 'Tools', 'icon' => 'tools', 'order' => 100, 'link' => | ||||||
|  | 		[ | ||||||
|  | 			['name' => 'Mass Account Actions', 'link' => 'mass_account', 'icon' => 'globe', 'order' => 10], | ||||||
|  | 			['name' => 'Mass Teleport Actions', 'link' => 'mass_teleport', 'icon' => 'globe', 'order' => 20], | ||||||
|  | 			['name' => 'Notepad', 'link' => 'notepad', 'icon' => 'marker', 'order' => 30], | ||||||
|  | 			['name' => 'phpinfo', 'link' => 'phpinfo', 'icon' => 'server', 'order' => 40], | ||||||
|  | 		], | ||||||
|  | 	], | ||||||
|  | 	['name' => 'Logs', 'icon' => 'bug', 'order' => 110, 'link' => | ||||||
|  | 		[ | ||||||
|  | 			['name' => 'Logs', 'link' => 'logs', 'icon' => 'book', 'order' => 10], | ||||||
|  | 			['name' => 'Reports', 'link' => 'reports', 'icon' => 'book', 'order' => 20], | ||||||
|  | 			['name' => 'Visitors', 'link' => 'visitors', 'icon' => 'user', 'order' => 30], | ||||||
|  | 		], | ||||||
|  | 	], | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | $hooks->trigger(HOOK_ADMIN_MENU); | ||||||
|  |  | ||||||
|  | usort($menus, function ($a, $b) { | ||||||
|  | 	return $a['order'] - $b['order']; | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | foreach ($menus as $i => $menu) { | ||||||
|  | 	if (isset($menu['link']) && is_array($menu['link'])) { | ||||||
|  | 		usort($menus[$i]['link'], function ($a, $b) { | ||||||
|  | 			return $a['order'] - $b['order']; | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | return $menus; | ||||||
| @@ -1,147 +1,15 @@ | |||||||
| *{ | .menu-text-li {color: #4b646f; background: #1a2226;} | ||||||
| 	margin:0; | .menu-text { | ||||||
| 	padding:0; | 	display: block; | ||||||
| } | 	padding: .5rem 1rem; | ||||||
| body { | 	white-space: nowrap; | ||||||
| 	font-family: Helvetica; |  | ||||||
| 	color: #313334; |  | ||||||
| 	background: /*#f9f9f9 #EEEEEE*/#F7F6F1; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| img {border: none;} | .sidebar-mini.sidebar-collapse .menu-text { | ||||||
|  | 	display: none; | ||||||
| a:link		{color: #000; text-decoration: none;} |  | ||||||
| a:visited	{color: #000; text-decoration: none;} |  | ||||||
| a:focus		{color: #000; text-decoration: none;} |  | ||||||
| a:active	{color: #000; text-decoration: underline;} |  | ||||||
| a:hover		{color: #000; text-decoration: underline;} |  | ||||||
| a.current	{font-weight: bold;} |  | ||||||
|  |  | ||||||
| h5.blue		{color: #6b7b95;} |  | ||||||
| h5.red		{color: #c17878;} |  | ||||||
| h5.green	{color: #78ba91;} |  | ||||||
| h5.purple	{color: #a87aad;} |  | ||||||
|  |  | ||||||
| h1, h2, h3, h4, h5, h6 {color: #313334; font-weight: bold;} |  | ||||||
| .separator {color:#BCE} |  | ||||||
| .margin-left{ |  | ||||||
| 	margin-left:5px; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| .button { background:#eee repeat-x 0 0; border:solid 1px #b1a874; color:#7f7f7f; font-size:11px; padding:2px 6px 2px 6px; cursor:pointer; line-height:14px !important; } | .myaac-table tbody tr:nth-child(even) {background: #FFF} /* light border */ | ||||||
| .button:hover { color:#333; border-color:#857b42; } | .myaac-table tbody tr:nth-child(odd) {background: #CCC} /* dark border */ | ||||||
|  | .myaac-table thead td {background: #000000; color: #ffffff !important;} /* vdark border */ | ||||||
| .field, .button { -moz-border-radius:4px; -webkit-border-radius:4px; } | .myaac-table tfoot td {background: #000000; color: #ffffff !important;} /* vdark border */ | ||||||
| .small-field, .button, .pagging a { -moz-border-radius:3px; -webkit-border-radius:3px; } |  | ||||||
|  |  | ||||||
| .table th { |  | ||||||
|     background-color: #4CAF50; |  | ||||||
|     color: white; |  | ||||||
| 	text-align: left; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .table, .table td, .table th{ |  | ||||||
| 	border: 1px solid #ddd; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .table th a:link {color: white; text-decoration: none;} |  | ||||||
| .table th a:link		{color: white; text-decoration: none;} |  | ||||||
| .table th a:visited	{color: white; text-decoration: none;} |  | ||||||
| .table th a:focus		{color: white; text-decoration: none;} |  | ||||||
| .table th a:active	{color: white; text-decoration: underline;} |  | ||||||
| .table th a:hover		{color: white; text-decoration: underline;} |  | ||||||
|  |  | ||||||
| .table tr:nth-child(odd) {background-color: #d1d1d1} |  | ||||||
|  |  | ||||||
| a.ico { color:#9d9c9a; font-size:10px; text-decoration: none; padding:0 0 0 14px; background-repeat:no-repeat; background-position:0 0; } |  | ||||||
| a.ico:hover { color:#333;} |  | ||||||
|  |  | ||||||
| #container{ |  | ||||||
| 	width:960px; |  | ||||||
| 	margin-left:auto; |  | ||||||
| 	margin-right:auto; |  | ||||||
| } |  | ||||||
| #header { |  | ||||||
| 	/*width: 960px;*/ |  | ||||||
| 	padding-left: auto; |  | ||||||
| 	padding-right: auto; |  | ||||||
| 	border-bottom: 1px dotted black; |  | ||||||
| 	margin-top: 40px; |  | ||||||
| } |  | ||||||
| #header h1 { |  | ||||||
| 	margin: 0; |  | ||||||
| 	padding-top: 20px; |  | ||||||
| 	text-align: center; |  | ||||||
| } |  | ||||||
| #sidebar{ |  | ||||||
| 	background: #FFF; |  | ||||||
| 	width: 170px; |  | ||||||
| 	float: left; |  | ||||||
| 	margin: 10px 0 10px 0; |  | ||||||
| 	padding: 10px; |  | ||||||
| 	border: 1px solid #CCC; |  | ||||||
| } |  | ||||||
| #content { |  | ||||||
| 	width: 740px; |  | ||||||
| 	float: right; |  | ||||||
| 	margin: 20px 0 10px 0; |  | ||||||
| 	padding: 10px; |  | ||||||
| } |  | ||||||
| #footer { |  | ||||||
| 	margin-top: 20px; |  | ||||||
| 	border-top: 1px dotted black; |  | ||||||
| 	text-align: center; |  | ||||||
| 	clear: both; |  | ||||||
| } |  | ||||||
| /********************* |  | ||||||
| 	Sidebar |  | ||||||
| *********************/ |  | ||||||
| #sidebar ul{ |  | ||||||
| 	list-style:none; |  | ||||||
| 	line-height:22px; |  | ||||||
| } |  | ||||||
| #sidebar ul li a,#sidebar ul li a:visited{ |  | ||||||
| 	padding-left:19px; |  | ||||||
| 	text-decoration:none; |  | ||||||
| 	margin:0 3px; |  | ||||||
| 	display:block; |  | ||||||
| } |  | ||||||
| #sidebar ul li a:hover{ |  | ||||||
| 	text-decoration:underline; |  | ||||||
| } |  | ||||||
| #sidebar ul li ul{ |  | ||||||
| 	margin-left:10px; |  | ||||||
| } |  | ||||||
| #sidebar h3{ |  | ||||||
| 	padding:2px; |  | ||||||
| 	font-size:14px; |  | ||||||
| } |  | ||||||
| /********************* |  | ||||||
| 	Status & version boxes |  | ||||||
| *********************/ |  | ||||||
| #status { |  | ||||||
| 	position: absolute; top: 10px; left: 10px; |  | ||||||
| 	margin: 0px; |  | ||||||
| 	float: right; |  | ||||||
| 	font-size: 12px; |  | ||||||
| } |  | ||||||
| #status .success { |  | ||||||
|   margin: 0px; |  | ||||||
| } |  | ||||||
| #version { |  | ||||||
| 	position: absolute; top: 10px; right: 10px; |  | ||||||
| 	float: right; |  | ||||||
| 	text-align: right; |  | ||||||
| 	font-size: 12px; |  | ||||||
| } |  | ||||||
| /********************* |  | ||||||
| 	Infobox |  | ||||||
| *********************/ |  | ||||||
| #infobox{ |  | ||||||
| 	border:1px solid #e9e8e3; |  | ||||||
| } |  | ||||||
| #infobox h3{ |  | ||||||
| 	background:#f7f6f1; |  | ||||||
| 	border-bottom:1px solid #e9e8e3; |  | ||||||
| 	color:#654322; |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -1,110 +1,203 @@ | |||||||
| <?php defined('MYAAC') or die('Direct access not allowed!'); ?> | <?php defined('MYAAC') or die('Direct access not allowed!'); ?> | ||||||
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | <!doctype html> | ||||||
| <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | <html lang="en"> | ||||||
| <head> | <head> | ||||||
|  | 	<?php $hooks->trigger(HOOK_ADMIN_HEAD_START); ?> | ||||||
| 	<?php echo template_header(true); ?> | 	<?php echo template_header(true); ?> | ||||||
| 	<title><?php echo $title . $config['title_separator'] . $config['lua']['serverName']; ?> - Powered by MyAAC</title> | 	<title><?php echo (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];?></title> | ||||||
| 	<link rel="stylesheet" type="text/css" href="<?php echo $template_path; ?>style.css" /> | 	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||||||
|  | 	<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/adminlte.min.css"> | ||||||
|  | 	<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/font-awesome.min.css"> | ||||||
|  | 	<?php if (isset($use_datatable)) { ?> | ||||||
|  | 	<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/datatables.bs.min.css"> | ||||||
|  | 	<?php } ?> | ||||||
|  | 	<link rel="stylesheet" type="text/css" href="<?php echo $template_path; ?>style.css"/> | ||||||
|  | 	<!--[if lt IE 9]> | ||||||
|  | 	<script src="<?php echo BASE_URL; ?>tools/js/html5shiv.min.js"></script> | ||||||
|  | 	<script src="<?php echo BASE_URL; ?>tools/js/respond.min.js"></script> | ||||||
|  | 	<![endif]--> | ||||||
|  | 	<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic"> | ||||||
|  | 	<?php $hooks->trigger(HOOK_ADMIN_HEAD_END); ?> | ||||||
| </head> | </head> | ||||||
| <body> | <body class="sidebar-mini "> | ||||||
| <?php if($page != 'tools'): ?> | <?php $hooks->trigger(HOOK_ADMIN_BODY_START); ?> | ||||||
| 	<div id="container"> | <?php if ($logged && admin()) { ?> | ||||||
| 		<div id="header"> | 	<div class="wrapper"> | ||||||
| 			<?php if($logged && admin()): ?> | 		<nav class="main-header navbar navbar-expand navbar-white navbar-light"> | ||||||
| 			<div id="status"> | 			<ul class="navbar-nav"> | ||||||
| 				<?php if($status['online']): ?> | 				<li class="nav-item"> | ||||||
| 				<p class="success" style="width: 120px; text-align: center;">Status: Online<br/> | 					<a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a> | ||||||
| 					<?php echo $status['uptimeReadable'] . ', ' . $status['players'] . '/' . $status['playersMax']; ?><br/> | 				</li> | ||||||
| 					<?php echo $config['lua']['ip'] . ' : ' . $config['lua']['loginPort']; ?> | 				<li class="nav-item d-none d-sm-inline-block"> | ||||||
| 				</p> | 					<a href="<?php echo ADMIN_URL; ?>" class="nav-link">Home</a> | ||||||
| 				<?php else: ?> | 				</li> | ||||||
| 				<p class="error" style="width: 120px; text-align: center;">Status: Offline</p> | 			</ul> | ||||||
| 				<?php endif; ?> | 			<ul class="navbar-nav ml-auto"> | ||||||
| 			</div> | 				<li class="nav-item"> | ||||||
| 			<div id="version">Version: <?php echo MYAAC_VERSION; ?> (<a id="update" href="?p=version">Check for updates</a>)<br/> | 					<a class="nav-link" data-widget="control-sidebar" data-slide="true" href="#"><i class="fas fa-th-large"></i></a> | ||||||
| 				Logged in as: <b><?php echo (USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()); ?></b><br/> | 				</li> | ||||||
| 				<a href="<?php echo BASE_URL; ?>" target="_blank">Preview</a> <span class="separator">|</span> <a href="?action=logout">Log out<img src="<?php echo BASE_URL; ?>images/icons/logout.png" alt="" title="Log out" /></a> | 			</ul> | ||||||
| 			</div> | 		</nav> | ||||||
| 			<?php endif; ?> | 		<aside class="main-sidebar sidebar-dark-info elevation-4"> | ||||||
| 			<h1><?php echo $config['lua']['serverName'] . (isset($title) ? ' - ' . $title : ''); ?> - Admin Panel</h1> | 			<a href="<?php echo ADMIN_URL; ?>" class="brand-link navbar-info"> | ||||||
| 		</div> | 				<img src="<?php echo ADMIN_URL; ?>images/logo.png" class="brand-image img-circle elevation-3" style="opacity: .8"> | ||||||
| 		<div id="wrapper"> | 				<span class="brand-text"><b>My</b>AAC</span> | ||||||
|  | 			</a> | ||||||
|  | 			<div class="sidebar"> | ||||||
|  | 				<nav class="mt-1"> | ||||||
|  | 					<ul class="nav nav-pills nav-sidebar flex-column nav-legacy nav-child-indent" data-widget="treeview" data-accordion="false"> | ||||||
|  | 						<li class="menu-text-li"> | ||||||
|  | 							<span class="menu-text"> | ||||||
|  | 								<a class="text-info" href="<?php echo BASE_URL; ?>" target="_blank"> | ||||||
|  | 									<?php echo $config['lua']['serverName'] ?> | ||||||
|  | 								</a> | ||||||
|  | 							</span> | ||||||
|  | 						</li> | ||||||
| 						<?php | 						<?php | ||||||
| 			if($logged && admin()) { | 						// name = Display name of link | ||||||
|  | 						// icon = fontawesome icon name without "fas fa-" | ||||||
|  | 						// link = Page link or use as array for sub items | ||||||
|  | 						$menus = require __DIR__ . '/menus.php'; | ||||||
|  |  | ||||||
|  | 						foreach ($menus as $category => $menu) { | ||||||
|  | 							if (isset($menu['disabled']) && $menu['disabled']) { | ||||||
|  | 								continue; | ||||||
|  | 							} | ||||||
|  |  | ||||||
|  | 							$has_child = is_array($menu['link']); | ||||||
|  | 							if (!$has_child) { ?> | ||||||
|  | 								<li class="nav-item"> | ||||||
|  | 									<a class="nav-link<?php echo(strpos($menu['link'], $page) !== false ? ' active' : '') ?>" href="?p=<?php echo $menu['link'] ?>"> | ||||||
|  | 										<i class="nav-icon fas fa-<?php echo($menu['icon'] ?? 'link') ?>"></i> | ||||||
|  | 										<p><?php echo $menu['name'] ?></p> | ||||||
|  | 									</a> | ||||||
|  | 								</li> | ||||||
|  | 								<?php | ||||||
|  | 							} else if ($has_child) { | ||||||
|  | 								$used_menu = null; | ||||||
|  | 								$nav_construct = ''; | ||||||
|  | 								foreach ($menu['link'] as $sub_category => $sub_menu) { | ||||||
|  | 									$nav_construct .= '<li class="nav-item"><a href="?p=' . $sub_menu['link'] . '" class="nav-link'; | ||||||
|  | 									if ($_SERVER['QUERY_STRING'] == 'p=' . $sub_menu['link']) { | ||||||
|  | 										$nav_construct .= ' active'; | ||||||
|  | 										$used_menu = true; | ||||||
|  | 									} | ||||||
|  | 									$nav_construct .= '"><i class="fas fa-' . ($sub_menu['icon'] ?? 'circle') . ' nav-icon"></i><p>' . $sub_menu['name'] . '</p></a></li>'; | ||||||
|  | 								} | ||||||
| 								?> | 								?> | ||||||
| 			<div id="sidebar"> | 								<li class="nav-item has-treeview<?php echo($used_menu ? ' menu-open' : '') ?>"> | ||||||
| 				<ul> | 									<a href="#" class="nav-link<?php echo($used_menu ? ' active' : '') ?>"> | ||||||
|  | 										<i class="nav-icon fas fa-<?php echo($menu['icon'] ?? 'link') ?>"></i> | ||||||
|  | 										<p><?php echo $menu['name'] ?></p><i class="right fas fa-angle-left"></i> | ||||||
|  | 									</a> | ||||||
|  | 									<ul class="nav nav-treeview"> | ||||||
|  | 										<?php echo $nav_construct; ?> | ||||||
|  | 									</ul> | ||||||
|  | 								</li> | ||||||
| 								<?php | 								<?php | ||||||
| 					$menus = array( |  | ||||||
| 						'Dashboard' => 'dashboard', |  | ||||||
| 						'Mailer' => 'mailer', |  | ||||||
| 						'Pages' => 'pages', |  | ||||||
| 						'Menus' => 'menus', |  | ||||||
| 						'Plugins' => 'plugins', |  | ||||||
| 						'Statistics' => 'statistics', |  | ||||||
| 						'Visitors' => 'visitors', |  | ||||||
| 						'Players' => 'players', |  | ||||||
| 						'Items' => 'items', |  | ||||||
| 						'Tools' => array( |  | ||||||
| 							'phpinfo' => 'phpinfo' |  | ||||||
| 						), |  | ||||||
| 						'Notepad' => 'notepad', |  | ||||||
| 						'Logs' => 'logs' |  | ||||||
| 					); |  | ||||||
|  |  | ||||||
| 					$i = 0; |  | ||||||
| 					foreach($menus as $_name => $_page) { |  | ||||||
| 						//echo '<a ' . ($page == $_page ? ' class="current"' : '') . 'href="?p=' . $_page . '">' . $_name . '</a>'; |  | ||||||
| 						echo '<li><h3>'; |  | ||||||
| 						$has_child = is_array($_page); |  | ||||||
| 						if(!$has_child) { |  | ||||||
| 							echo '<a href="?p=' . $_page . '">'; |  | ||||||
| 							if($page == $_page) echo '<u>'; |  | ||||||
| 								echo $_name; |  | ||||||
| 							if($page == $_page) echo '</u>'; |  | ||||||
| 							echo '</a>'; |  | ||||||
| 							} | 							} | ||||||
| 						else |  | ||||||
| 							echo $_name; |  | ||||||
|  |  | ||||||
| 						echo '</h3>'; |  | ||||||
| 						if($has_child) { |  | ||||||
| 							echo '<ul>'; |  | ||||||
| 							foreach($_page as $__name => $__page) |  | ||||||
| 								echo '<li><a href="?p=' . $__page . '">'; |  | ||||||
| 								if($page == $__page) echo '<u>'; |  | ||||||
| 									echo $__name; |  | ||||||
| 								if($page == $__page) echo '</u>'; |  | ||||||
| 								echo '</a></li>'; |  | ||||||
| 							echo '</ul>'; |  | ||||||
| 						} |  | ||||||
| 						echo '</li>'; |  | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
| 						$query = $db->query('SELECT `name`, `page`, `flags` FROM `' . TABLE_PREFIX . 'admin_menu` ORDER BY `ordering`'); | 						$query = $db->query('SELECT `name`, `page`, `flags` FROM `' . TABLE_PREFIX . 'admin_menu` ORDER BY `ordering`'); | ||||||
| 						$menu_db = $query->fetchAll(); | 						$menu_db = $query->fetchAll(); | ||||||
| 					foreach($menu_db as $item) { | 						foreach ($menu_db as $item) { | ||||||
| 						if($item['flags'] == 0 || hasFlag($item['flags'])) { | 							if ($item['flags'] == 0 || hasFlag($item['flags'])) { ?> | ||||||
| 							echo '<li><h3> | 								<li class="nav-item"> | ||||||
| 							<a href="?p=' . $item['page'] . '">'; | 									<a class="nav-link<?php echo($page == $item['page'] ? ' active' : '') ?>" href="?p=<?php echo $item['page'] ?>"> | ||||||
| 							if($page == $item['page']) echo '<u>'; | 										<i class="nav-icon fas fa-link"></i> | ||||||
| 							echo $item['name']; | 										<p><?php echo $item['name'] ?></p> | ||||||
| 							if($page == $item['page']) echo '</u>'; | 									</a> | ||||||
| 							echo '</a></h3></li>'; | 								</li> | ||||||
|  | 								<?php | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 						?> | 						?> | ||||||
| 					</ul> | 					</ul> | ||||||
|  | 				</nav> | ||||||
| 			</div> | 			</div> | ||||||
| 			<?php | 		</aside> | ||||||
| 			} |  | ||||||
| 			?> | 		<div class="content-wrapper" style="min-height: 823px;"> | ||||||
| 			<div id="content"><?php echo $content; ?></div> | 			<div class="content-header"> | ||||||
|  | 				<div class="container-fluid"> | ||||||
|  | 					<div class="row mb-2"> | ||||||
|  | 						<div class="col-sm-6"> | ||||||
|  | 							<h3 class="m-0 text-dark"><?php echo(isset($title) ? $title : ''); ?><small> - Admin Panel</small></h3> | ||||||
|  | 						</div> | ||||||
|  | 						<div class="col-sm-6"> | ||||||
|  | 							<div class="float-sm-right d-none d-sm-inline"> | ||||||
|  | 								<span class="p-2 right badge badge-<?php echo((isset($status['online']) and $status['online']) ? 'success' : 'danger'); ?>"><?php echo $config['lua']['serverName'] ?></span> | ||||||
|  | 							</div> | ||||||
|  | 						</div> | ||||||
|  | 					</div> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="content"> | ||||||
|  | 				<div class="container-fluid"> | ||||||
|  | 					<?php echo $content; ?> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  |  | ||||||
|  | 		<aside class="control-sidebar control-sidebar-dark"> | ||||||
|  | 			<div class="p-3"> | ||||||
|  | 				<h4>Account:</h4> | ||||||
|  | 				<p><h5><a href="?action=logout"><i class="fas fa-sign-out-alt text-danger"></i> Log out</h5></a> | ||||||
|  | 				<small>This will log you out</small></p> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="p-3"> | ||||||
|  | 				<h4>Site:</h4> | ||||||
|  | 				<p><h5><a href="<?php echo BASE_URL; ?>" target="_blank"><i class="far fa-eye text-blue"></i> Preview</a></h5> | ||||||
|  | 				<small>This will open a new tab</small></p> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="p-3"> | ||||||
|  | 				<h4>Version:</h4> | ||||||
|  | 				<p><h5><a href="?p=version"><i class="fas fa-code-branch"></i> <?php echo MYAAC_VERSION; ?></a></h5> | ||||||
|  | 				<small>Check for updates</small></p> | ||||||
|  | 			</div> | ||||||
|  | 			<div class="p-3"> | ||||||
|  | 				<h4>Site:</h4> | ||||||
|  | 				<p><h5><a href="https://github.com/slawkens/myaac" target="_blank"><i class="fab fa-github"></i> Github</a></h5> | ||||||
|  | 				<small>Goto GitHub Page</small></p> | ||||||
|  |  | ||||||
|  | 				<p><h5><a href="http://my-aac.org/" target="_blank"><i class="fas fa-shoe-prints"></i> MyAAC Official</a></h5> | ||||||
|  | 				<small>Goto MyAAC Official Website</small></p> | ||||||
|  |  | ||||||
|  | 				<p><h5><a href="?p=open_source"><i class="fas fa-wrench"></i> Open Source</a></h5> | ||||||
|  | 				<small>View Open Source Software MyAAC is using</small></p> | ||||||
|  | 			</div> | ||||||
|  | 		</aside> | ||||||
|  |  | ||||||
|  | 		<footer class="main-footer"> | ||||||
|  | 			<div class="float-sm-right d-none d-sm-inline"> | ||||||
|  | 				<span class="p-2 right badge badge-<?php echo((isset($status['online']) and $status['online']) ? 'success' : 'danger'); ?>"><?php echo $config['lua']['serverName'] ?></span> | ||||||
| 			</div> | 			</div> | ||||||
| 		<div id="footer"> |  | ||||||
| 			<?php echo base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4='); ?> | 			<?php echo base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4='); ?> | ||||||
|  | 		</footer> | ||||||
|  | 		<div id="sidebar-overlay"></div> | ||||||
| 	</div> | 	</div> | ||||||
| 	</div> |  | ||||||
| <?php endif; ?> | <?php } else if (!$logged && !admin()) { | ||||||
|  | 	echo $content; | ||||||
|  | } | ||||||
|  | ?> | ||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * @var OTS_Account $account_logged | ||||||
|  |  */ | ||||||
|  | if ($logged && admin()) { | ||||||
|  | 	$twig->display('admin-bar.html.twig', [ | ||||||
|  | 		'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId() | ||||||
|  | 	]); | ||||||
|  | } | ||||||
|  | ?> | ||||||
|  | <script src="<?php echo BASE_URL; ?>tools/ext/bootstrap/js/bootstrap.min.js"></script> | ||||||
|  | <script src="<?php echo BASE_URL; ?>tools/ext/jquery-ui/jquery-ui.min.js"></script> | ||||||
|  | <?php if (isset($use_datatable))  { ?> | ||||||
|  | <script src="<?php echo BASE_URL; ?>tools/js/datatables.min.js"></script> | ||||||
|  | <script src="<?php echo BASE_URL; ?>tools/js/datatables.bs.min.js"></script> | ||||||
|  | <?php } ?> | ||||||
|  | <script src="<?php echo BASE_URL; ?>tools/js/adminlte.min.js"></script> | ||||||
|  | <?php $hooks->trigger(HOOK_ADMIN_BODY_END); ?> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -1,8 +1,11 @@ | |||||||
| <?php | <?php | ||||||
| require('../../common.php'); | const MYAAC_ADMIN = true; | ||||||
| require(SYSTEM . 'functions.php'); | const IGNORE_SET_LAST_VISIT = true; | ||||||
| require(SYSTEM . 'init.php'); |  | ||||||
| require(SYSTEM . 'login.php'); | require '../../common.php'; | ||||||
|  | require SYSTEM . 'functions.php'; | ||||||
|  | require SYSTEM . 'init.php'; | ||||||
|  | require SYSTEM . 'login.php'; | ||||||
|  |  | ||||||
| if(!admin()) | if(!admin()) | ||||||
| 	die('Access denied.'); | 	die('Access denied.'); | ||||||
| @@ -11,4 +14,3 @@ if(!function_exists('phpinfo')) | |||||||
| 	die('phpinfo() disabled on this web server.'); | 	die('phpinfo() disabled on this web server.'); | ||||||
|  |  | ||||||
| phpinfo(); | phpinfo(); | ||||||
| ?> |  | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								admin/tools/reload_data.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,48 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Project: MyAAC | ||||||
|  |  *     Automatic Account Creator for Open Tibia Servers | ||||||
|  |  * | ||||||
|  |  * This is free software; you can redistribute it and/or | ||||||
|  |  * modify it under the terms of the GNU Lesser General Public | ||||||
|  |  * License as published by the Free Software Foundation; either | ||||||
|  |  * version 2.1 of the License, or (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This software is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||||
|  |  * Lesser General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU Lesser General Public | ||||||
|  |  * License along with this library; if not, write to the Free Software | ||||||
|  |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  |  * | ||||||
|  |  * @package   MyAAC | ||||||
|  |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  |  * @copyright 2020 MyAAC | ||||||
|  |  * @link      https://my-aac.org | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | use MyAAC\DataLoader; | ||||||
|  |  | ||||||
|  | const MYAAC_ADMIN = true; | ||||||
|  | const IGNORE_SET_LAST_VISIT = true; | ||||||
|  |  | ||||||
|  | require '../../common.php'; | ||||||
|  | require SYSTEM . 'functions.php'; | ||||||
|  | require SYSTEM . 'init.php'; | ||||||
|  | require SYSTEM . 'login.php'; | ||||||
|  |  | ||||||
|  | if (!admin()) | ||||||
|  | 	die('Access denied.'); | ||||||
|  |  | ||||||
|  | ini_set('max_execution_time', 300); | ||||||
|  | ob_implicit_flush(); | ||||||
|  | @ob_end_flush(); | ||||||
|  | header('X-Accel-Buffering: no'); | ||||||
|  |  | ||||||
|  | require LOCALE . 'en/main.php'; | ||||||
|  | require LOCALE . 'en/install.php'; | ||||||
|  |  | ||||||
|  | DataLoader::setLocale($locale); | ||||||
|  | DataLoader::load(); | ||||||
							
								
								
									
										42
									
								
								admin/tools/settings_save.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,42 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | use MyAAC\Settings; | ||||||
|  |  | ||||||
|  | const MYAAC_ADMIN = true; | ||||||
|  | const IGNORE_SET_LAST_VISIT = true; | ||||||
|  |  | ||||||
|  | require '../../common.php'; | ||||||
|  | require SYSTEM . 'functions.php'; | ||||||
|  | require SYSTEM . 'init.php'; | ||||||
|  | require SYSTEM . 'login.php'; | ||||||
|  |  | ||||||
|  | if(!admin()) { | ||||||
|  | 	http_response_code(500); | ||||||
|  | 	die('Access denied.'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | csrfProtect(); | ||||||
|  |  | ||||||
|  | if (!isset($_REQUEST['plugin'])) { | ||||||
|  | 	http_response_code(500); | ||||||
|  | 	die('Please enter plugin name.'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (!isset($_POST['settings'])) { | ||||||
|  | 	http_response_code(500); | ||||||
|  | 	die('Please enter settings.'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $settings = Settings::getInstance(); | ||||||
|  |  | ||||||
|  | $success = $settings->save($_REQUEST['plugin'], $_POST['settings']); | ||||||
|  |  | ||||||
|  | $errors = $settings->getErrors(); | ||||||
|  | if (count($errors) > 0) { | ||||||
|  | 	http_response_code(500); | ||||||
|  | 	die(implode('<br/>', $errors)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if ($success) { | ||||||
|  | 	echo 'Saved at ' . date('H:i'); | ||||||
|  | } | ||||||
| @@ -1,9 +1,12 @@ | |||||||
| <?php | <?php | ||||||
| require('../../common.php'); | const MYAAC_ADMIN = true; | ||||||
| require(SYSTEM . 'init.php'); | const IGNORE_SET_LAST_VISIT = true; | ||||||
| require(SYSTEM . 'functions.php'); |  | ||||||
| require(SYSTEM . 'status.php'); | require '../../common.php'; | ||||||
| require(SYSTEM . 'login.php'); | require SYSTEM . 'init.php'; | ||||||
|  | require SYSTEM . 'functions.php'; | ||||||
|  | require SYSTEM . 'status.php'; | ||||||
|  | require SYSTEM . 'login.php'; | ||||||
|  |  | ||||||
| if(!admin()) | if(!admin()) | ||||||
| 	die('Access denied.'); | 	die('Access denied.'); | ||||||
|   | |||||||
							
								
								
									
										54
									
								
								admin/tools/upload_image.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,54 @@ | |||||||
|  | <?php | ||||||
|  | const MYAAC_ADMIN = true; | ||||||
|  | const IGNORE_SET_LAST_VISIT = true; | ||||||
|  |  | ||||||
|  | require '../../common.php'; | ||||||
|  | require SYSTEM . 'functions.php'; | ||||||
|  | require SYSTEM . 'init.php'; | ||||||
|  | require SYSTEM . 'login.php'; | ||||||
|  |  | ||||||
|  | if(!admin()) | ||||||
|  | 	die('Access denied.'); | ||||||
|  |  | ||||||
|  | // Don't attempt to process the upload on an OPTIONS request | ||||||
|  | if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { | ||||||
|  | 	header('Access-Control-Allow-Methods: POST, OPTIONS'); | ||||||
|  | 	return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $imageFolder = BASE . EDITOR_IMAGES_DIR; | ||||||
|  |  | ||||||
|  | reset ($_FILES); | ||||||
|  | $temp = current($_FILES); | ||||||
|  | if (is_uploaded_file($temp['tmp_name'])) { | ||||||
|  | 	header('Access-Control-Allow-Credentials: true'); | ||||||
|  | 	header('P3P: CP="There is no P3P policy."'); | ||||||
|  |  | ||||||
|  | 	// Sanitize input | ||||||
|  | 	if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $temp['name'])) { | ||||||
|  | 		header('HTTP/1.1 400 Invalid file name.'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Verify extension | ||||||
|  | 	$ext = strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)); | ||||||
|  | 	if (!in_array($ext, ['gif', 'jpg', 'png'])) { | ||||||
|  | 		header('HTTP/1.1 400 Invalid extension.'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	do { | ||||||
|  | 		$randomName = generateRandomString(8). ".$ext"; | ||||||
|  | 		$fileToWrite = $imageFolder . $randomName; | ||||||
|  | 	} while (file_exists($fileToWrite)); | ||||||
|  |  | ||||||
|  | 	move_uploaded_file($temp['tmp_name'], $fileToWrite); | ||||||
|  |  | ||||||
|  | 	$returnPathToImage = BASE_URL . EDITOR_IMAGES_DIR . $randomName; | ||||||
|  | 	echo json_encode(['location' => $returnPathToImage]); | ||||||
|  | } else { | ||||||
|  | 	// Notify editor that the upload failed | ||||||
|  | 	header('HTTP/1.1 500 Server Error'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										197
									
								
								common.php
									
									
									
									
									
								
							
							
						
						| @@ -20,89 +20,156 @@ | |||||||
|  * |  * | ||||||
|  * @package   MyAAC |  * @package   MyAAC | ||||||
|  * @author    Slawkens <slawkens@gmail.com> |  * @author    Slawkens <slawkens@gmail.com> | ||||||
|  * @copyright 2017 MyAAC |  * @copyright 2024 MyAAC | ||||||
|  * @link      http://my-aac.org |  * @link      https://my-aac.org | ||||||
|  */ |  */ | ||||||
| session_start(); | if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); | ||||||
|  |  | ||||||
| define('MYAAC', true); | const MYAAC = true; | ||||||
| define('MYAAC_VERSION', '0.7.4'); | const MYAAC_VERSION = '1.8.3'; | ||||||
| define('DATABASE_VERSION', 20); | const DATABASE_VERSION = 46; | ||||||
| define('TABLE_PREFIX', 'myaac_'); | const TABLE_PREFIX = 'myaac_'; | ||||||
| define('START_TIME', microtime(true)); | define('START_TIME', microtime(true)); | ||||||
| define('MYAAC_OS', (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? 'WINDOWS' : (strtoupper(PHP_OS) == 'DARWIN' ? 'MAC' : 'LINUX')); | define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX')); | ||||||
|  | define('IS_CLI', in_array(php_sapi_name(), ['cli', 'phpdb'])); | ||||||
|  |  | ||||||
| // account flags | // account flags | ||||||
| define('FLAG_ADMIN', 1); | const FLAG_NONE = 0; | ||||||
| define('FLAG_SUPER_ADMIN', 2); | const FLAG_ADMIN = 1; | ||||||
| define('FLAG_CONTENT_PAGES', 4); | const FLAG_SUPER_ADMIN = 2; | ||||||
| define('FLAG_CONTENT_MAILER', 8); | const FLAG_SUPER_BOTH = 3; | ||||||
| define('FLAG_CONTENT_NEWS', 16); | const FLAG_CONTENT_PAGES = 4; | ||||||
| define('FLAG_CONTENT_FORUM', 32); | const FLAG_CONTENT_MAILER = 8; | ||||||
| define('FLAG_CONTENT_COMMANDS', 64); | const FLAG_CONTENT_NEWS = 16; | ||||||
| define('FLAG_CONTENT_SPELLS', 128); | const FLAG_CONTENT_FORUM = 32; | ||||||
| define('FLAG_CONTENT_MONSTERS', 256); | const FLAG_CONTENT_COMMANDS = 64; | ||||||
| define('FLAG_CONTENT_GALLERY', 512); | const FLAG_CONTENT_SPELLS = 128; | ||||||
| define('FLAG_CONTENT_VIDEOS', 1024); | const FLAG_CONTENT_MONSTERS = 256; | ||||||
| define('FLAG_CONTENT_FAQ', 2048); | const FLAG_CONTENT_GALLERY = 512; | ||||||
| define('FLAG_CONTENT_MENUS', 4096); | const FLAG_CONTENT_VIDEOS = 1024; | ||||||
|  | const FLAG_CONTENT_FAQ = 2048; | ||||||
|  | const FLAG_CONTENT_MENUS = 4096; | ||||||
|  | const FLAG_CONTENT_PLAYERS = 8192; | ||||||
|  |  | ||||||
|  | // account access types | ||||||
|  | const ACCOUNT_WEB_FLAGS = [ | ||||||
|  | 	FLAG_NONE => 'None', | ||||||
|  | 	FLAG_ADMIN =>'Admin', | ||||||
|  | 	FLAG_SUPER_ADMIN => 'Super Admin', | ||||||
|  | 	FLAG_SUPER_BOTH =>'(Admin + Super Admin)', | ||||||
|  | ]; | ||||||
|  |  | ||||||
| // news | // news | ||||||
| define('NEWS', 1); | const NEWS = 1; | ||||||
| define('TICKER', 2); | const TICKER = 2; | ||||||
| define('ARTICLE', 3); | const ARTICLE = 3; | ||||||
|  |  | ||||||
|  | // here you can change location of admin panel | ||||||
|  | // you need also to rename folder "admin" | ||||||
|  | // this may improve security | ||||||
|  | const ADMIN_PANEL_FOLDER = 'admin'; | ||||||
|  |  | ||||||
| // directories | // directories | ||||||
| define('BASE', dirname(__FILE__) . '/'); | const BASE = __DIR__ . '/'; | ||||||
| define('ADMIN', BASE . 'admin/'); | const ADMIN = BASE . ADMIN_PANEL_FOLDER . '/'; | ||||||
| define('SYSTEM', BASE . 'system/'); | const SYSTEM = BASE . 'system/'; | ||||||
| define('CACHE', SYSTEM . 'cache/'); | const CACHE = SYSTEM . 'cache/'; | ||||||
| define('LOCALE', SYSTEM . 'locale/'); | const LOCALE = SYSTEM . 'locale/'; | ||||||
| define('LIBS', SYSTEM . 'libs/'); | const LIBS = SYSTEM . 'libs/'; | ||||||
| define('LOGS', SYSTEM . 'logs/'); | const LOGS = SYSTEM . 'logs/'; | ||||||
| define('PAGES', SYSTEM . 'pages/'); | const PAGES = SYSTEM . 'pages/'; | ||||||
| define('PLUGINS', BASE . 'plugins/'); | const PLUGINS = BASE . 'plugins/'; | ||||||
| define('TEMPLATES', BASE . 'templates/'); | const TEMPLATES = BASE . 'templates/'; | ||||||
| define('TOOLS', BASE . 'tools/'); | const TOOLS = BASE . 'tools/'; | ||||||
|  | const VENDOR = BASE . 'vendor/'; | ||||||
|  |  | ||||||
|  | // other dirs | ||||||
|  | const SESSIONS_DIR = SYSTEM . 'php_sessions'; | ||||||
|  | const GUILD_IMAGES_DIR = 'images/guilds/'; | ||||||
|  | const EDITOR_IMAGES_DIR = 'images/editor/'; | ||||||
|  | const GALLERY_DIR = 'images/gallery/'; | ||||||
|  |  | ||||||
| // menu categories | // menu categories | ||||||
| define('MENU_CATEGORY_NEWS', 1); | const MENU_CATEGORY_NEWS = 1; | ||||||
| define('MENU_CATEGORY_ACCOUNT', 2); | const MENU_CATEGORY_ACCOUNT = 2; | ||||||
| define('MENU_CATEGORY_COMMUNITY', 3); | const MENU_CATEGORY_COMMUNITY = 3; | ||||||
| define('MENU_CATEGORY_FORUM', 4); | const MENU_CATEGORY_FORUM = 4; | ||||||
| define('MENU_CATEGORY_LIBRARY', 5); | const MENU_CATEGORY_LIBRARY = 5; | ||||||
| define('MENU_CATEGORY_SHOP', 6); | const MENU_CATEGORY_SHOP = 6; | ||||||
|  |  | ||||||
| // otserv versions | // otserv versions | ||||||
| define('OTSERV', 1); | const OTSERV = 1; | ||||||
| define('OTSERV_06', 2); | const OTSERV_06 = 2; | ||||||
| define('OTSERV_FIRST', OTSERV); | const OTSERV_FIRST = OTSERV; | ||||||
| define('OTSERV_LAST', OTSERV_06); | const OTSERV_LAST = OTSERV_06; | ||||||
| define('TFS_02', 3); | const TFS_02 = 3; | ||||||
| define('TFS_03', 4); | const TFS_03 = 4; | ||||||
| define('TFS_FIRST', TFS_02); | const TFS_FIRST = TFS_02; | ||||||
| define('TFS_LAST', TFS_03); | const TFS_LAST = TFS_03; | ||||||
|  |  | ||||||
| // basedir | // other definitions | ||||||
| $basedir = ''; | const MAIL_MAIL = 0; | ||||||
| $tmp = explode('/', $_SERVER['SCRIPT_NAME']); | const MAIL_SMTP = 1; | ||||||
| $size = sizeof($tmp) - 1; |  | ||||||
| for($i = 1; $i < $size; $i++) |  | ||||||
| 	$basedir .= '/' . $tmp[$i]; |  | ||||||
|  |  | ||||||
| $basedir = str_replace('/admin', '', $basedir); | const SMTP_SECURITY_NONE = 0; | ||||||
| $basedir = str_replace('/install', '', $basedir); | const SMTP_SECURITY_SSL = 1; | ||||||
| define('BASE_DIR', $basedir); | const SMTP_SECURITY_TLS = 2; | ||||||
|  |  | ||||||
| if(isset($_SERVER['HTTP_HOST'])) { | const ACCOUNT_NUMBER_LENGTH = 8; | ||||||
| 	if (isset($_SERVER['HTTPS'][0]) && $_SERVER['HTTPS'] == 'on') |  | ||||||
| 		define('SERVER_URL', 'https://' . $_SERVER['HTTP_HOST']); |  | ||||||
| 	else |  | ||||||
| 		define('SERVER_URL', 'http://' . $_SERVER['HTTP_HOST']); |  | ||||||
|  |  | ||||||
|  | if (!IS_CLI) { | ||||||
|  | 	session_save_path(SESSIONS_DIR); | ||||||
|  | 	session_start(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (file_exists(BASE . 'config.local.php')) { | ||||||
|  | 	require BASE . 'config.local.php'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | require SYSTEM . 'base.php'; | ||||||
|  | define('BASE_DIR', $baseDir); | ||||||
|  |  | ||||||
|  | if(!IS_CLI) { | ||||||
|  | 	if (isset($config['site_url'])) { | ||||||
|  | 		$hasSlashAtEnd = ($config['site_url'][strlen($config['site_url']) - 1] == '/'); | ||||||
|  |  | ||||||
|  | 		define('SERVER_URL', $config['site_url']); | ||||||
|  | 		define('BASE_URL', SERVER_URL . ($hasSlashAtEnd ? '' : '/')); | ||||||
|  | 		define('ADMIN_URL', SERVER_URL . ($hasSlashAtEnd ? '' : '/') . ADMIN_PANEL_FOLDER . '/'); | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		define('SERVER_URL', 'http' . (isHttps() ? 's' : '') . '://' . $baseHost); | ||||||
| 		define('BASE_URL', SERVER_URL . BASE_DIR . '/'); | 		define('BASE_URL', SERVER_URL . BASE_DIR . '/'); | ||||||
| 	define('ADMIN_URL', SERVER_URL . BASE_DIR . '/admin/'); | 		define('ADMIN_URL', SERVER_URL . BASE_DIR . '/' . ADMIN_PANEL_FOLDER . '/'); | ||||||
|  |  | ||||||
| 		//define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); | 		//define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** @var array $config */ | ||||||
|  | ini_set('log_errors', 1); | ||||||
|  | if(@$config['env'] === 'dev' || defined('MYAAC_INSTALL')) { | ||||||
|  | 	ini_set('display_errors', 1); | ||||||
|  | 	ini_set('display_startup_errors', 1); | ||||||
|  | 	error_reporting(E_ALL); | ||||||
|  | } | ||||||
|  | else { | ||||||
|  | 	ini_set('display_errors', 0); | ||||||
|  | 	ini_set('display_startup_errors', 0); | ||||||
|  | 	error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $autoloadFile = VENDOR . 'autoload.php'; | ||||||
|  | if (!is_file($autoloadFile)) { | ||||||
|  | 	throw new RuntimeException('The vendor folder is missing. Please download Composer: <a href="https://getcomposer.org/download">https://getcomposer.org/download</a>, install it and execute in the main MyAAC directory this command: <b>composer install</b>. Or download MyAAC from <a href="https://github.com/slawkens/myaac/releases">GitHub releases</a>, which includes Vendor folder.'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | require $autoloadFile; | ||||||
|  |  | ||||||
|  | function isHttps(): bool | ||||||
|  | { | ||||||
|  | 	return | ||||||
|  | 		(!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https') | ||||||
|  | 		|| (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') | ||||||
|  | 		|| (isset($_SERVER['SERVER_PORT']) && (int) $_SERVER['SERVER_PORT'] === 443); | ||||||
| } | } | ||||||
| ?> |  | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,33 @@ | |||||||
|  | { | ||||||
|  |     "require": { | ||||||
|  |         "php": "^8.1", | ||||||
|  |         "ext-pdo": "*", | ||||||
|  |         "ext-pdo_mysql": "*", | ||||||
|  |         "ext-json": "*", | ||||||
|  |         "ext-xml": "*", | ||||||
|  |         "ext-dom": "*", | ||||||
|  |         "phpmailer/phpmailer": "^6.1", | ||||||
|  |         "composer/semver": "^3.2", | ||||||
|  |         "twig/twig": "^3.11", | ||||||
|  |         "erusev/parsedown": "^1.7", | ||||||
|  |         "nikic/fast-route": "^1.3", | ||||||
|  |         "matomo/device-detector": "^6.0", | ||||||
|  |         "illuminate/database": "^10.18", | ||||||
|  |         "peppeocchi/php-cron-scheduler": "4.*", | ||||||
|  |         "symfony/console": "^6.4", | ||||||
|  |         "symfony/string": "^6.4", | ||||||
|  |         "symfony/var-dumper": "^6.4", | ||||||
|  |         "filp/whoops": "^2.15", | ||||||
|  |         "maximebf/debugbar": "1.*", | ||||||
|  |         "guzzlehttp/guzzle": "7.9.3" | ||||||
|  |     }, | ||||||
|  |     "require-dev": { | ||||||
|  |         "phpstan/phpstan": "^1.10" | ||||||
|  |     }, | ||||||
|  |     "autoload": { | ||||||
|  |         "psr-4": { | ||||||
|  |             "MyAAC\\": "system/src" | ||||||
|  |         }, | ||||||
|  |         "files": ["system/src/global.php"] | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										3455
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						| @@ -1,3 +0,0 @@ | |||||||
| <?php |  | ||||||
| 	// place for your configuration directives, so you can later easily update myaac |  | ||||||
| ?> |  | ||||||
							
								
								
									
										249
									
								
								config.php
									
									
									
									
									
								
							
							
						
						| @@ -1,249 +0,0 @@ | |||||||
| <?php |  | ||||||
| /** |  | ||||||
|  * This is MyAAC's Main Configuration file |  | ||||||
|  * |  | ||||||
|  * All the default values are kept here, you should not modify it but use |  | ||||||
|  * a config.local.php file instead to override the settings from here. |  | ||||||
|  * |  | ||||||
|  * This is a piece of PHP code so PHP syntax applies! |  | ||||||
|  * For boolean values please use true/false. |  | ||||||
|  * |  | ||||||
|  * Minimally 'server_path' directive have to be filled, other options are optional. |  | ||||||
|  * |  | ||||||
|  * @package   MyAAC |  | ||||||
|  * @author    Slawkens <slawkens@gmail.com> |  | ||||||
|  * @copyright 2017 MyAAC |  | ||||||
|  * @link      http://my-aac.org |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| $config = array( |  | ||||||
| 	// directories & files |  | ||||||
| 	'server_path' => '', // path to the server directory (same directory where config file is located) |  | ||||||
|  |  | ||||||
| 	'template' => 'kathrine', // template used by website (kathrine, tibiacom) |  | ||||||
| 	'template_allow_change' => true, // allow users to choose their own template while browsing website? |  | ||||||
|  |  | ||||||
| 	'vocations_amount' => 4, // how much basic vocations your server got (without promotion) |  | ||||||
|  |  | ||||||
| 	// what client version are you using on this OT? |  | ||||||
| 	// used for the Downloads page and some templates aswell |  | ||||||
| 	'client' => 1098, // 954 = client 9.54 |  | ||||||
|  |  | ||||||
| 	'session_prefix' => 'myaac_', // must be unique for every site on your server |  | ||||||
| 	'friendly_urls' => false, // mod_rewrite is required for this, it makes links looks more elegant to eye, and also are SEO friendly (example: http://my-aac.org/guilds/Testing instead of http://my-aac.org/?subtopic=guilds&name=Testing). Remember to rename .htaccess.dist to .htaccess |  | ||||||
| 	'gzip_output' => false, // gzip page content before sending it to the browser, uses less bandwidth but more cpu cycles |  | ||||||
|  |  | ||||||
| 	// gesior backward support (templates & pages) |  | ||||||
| 	// allows using gesior templates and pages with myaac |  | ||||||
| 	// might bring some performance when disabled |  | ||||||
| 	'backward_support' => true, |  | ||||||
|  |  | ||||||
| 	// head options (html) |  | ||||||
| 	'meta_description' => 'Tibia is a free massive multiplayer online role playing game (MMORPG).', // description of the site |  | ||||||
| 	'meta_keywords' => 'free online game, free multiplayer game, ots, open tibia server', // keywords list separated by commas |  | ||||||
| 	'title_separator' => ' - ', |  | ||||||
|  |  | ||||||
| 	// footer |  | ||||||
| 	'footer' => ''/*'<br/>Your Server © 2016. All rights reserved.'*/, |  | ||||||
|  |  | ||||||
| 	'debug_level' => 0, // 0 - disabled, 1 - show load time, 2 - show db query counter, 3 - both, 4 - memory usage, 5 - load time & memory usage, 6 - queries & memory usage, 7 - all |  | ||||||
|  |  | ||||||
| 	'language' => 'en', // default language (currently only 'en' available) |  | ||||||
| 	'language_allow_change' => false, |  | ||||||
|  |  | ||||||
| 	'visitors_counter' => true, |  | ||||||
| 	'visitors_counter_ttl' => 10, // how long visitor will be marked as online (in minutes) |  | ||||||
| 	'views_counter' => true, |  | ||||||
|  |  | ||||||
| 	// cache system. by default file cache is used |  | ||||||
| 	'cache_engine' => 'auto', // apc, eaccelerator, xcache, file, auto, or blank to disable. |  | ||||||
| 	'cache_prefix' => 'myaac_', // have to be unique if running more MyAAC instances on the same server (except file system cache) |  | ||||||
|  |  | ||||||
| 	// database details (leave blank for auto detect from config.lua) |  | ||||||
| 	'database_host' => '', |  | ||||||
| 	'database_port' => '', // leave blank to default 3306 |  | ||||||
| 	'database_user' => '', |  | ||||||
| 	'database_password' => '', |  | ||||||
| 	'database_name' => '', |  | ||||||
|  |  | ||||||
| 	// multiworld system (only TFS 0.3) |  | ||||||
| 	'multiworld' => false, // use multiworld system? |  | ||||||
| 	'worlds' => array( // list of worlds |  | ||||||
| 		//'1' => 'Your World Name', |  | ||||||
| 		//'2' => 'Your Second World Name' |  | ||||||
| 	), |  | ||||||
|  |  | ||||||
| 	// images |  | ||||||
| 	'outfit_images_url' => 'http://outfit-images.ots.me/outfit.php', // set to animoutfit.php for animated outfit |  | ||||||
| 	'item_images_url' => 'http://item-images.ots.me/960/', // set to images/items if you host your own items in images folder |  | ||||||
|  |  | ||||||
| 	// account |  | ||||||
| 	'account_management' => true, // disable if you're using other method to manage users (fe. tfs account manager) |  | ||||||
| 	'account_mail_verify' => false, // force users to confirm their email addresses when registering account |  | ||||||
| 	'account_mail_unique' => true, // email addresses cannot be duplicated? (one account = one email) |  | ||||||
| 	'account_premium_days' => 0, // default premium days on new account |  | ||||||
| 	'account_premium_points' => 0, // default premium points on new account |  | ||||||
| 	'account_welcome_mail' => true, // send welcome email when user registers |  | ||||||
| 	'account_mail_change' => 2, // how many days user need to change email to account - block hackers |  | ||||||
| 	'account_country' => true, // user will be able to set country of origin when registering account, this information will be viewable in others places aswell |  | ||||||
| 	'account_country_recognize' => true, // should country of user be automatically recognized by his IP? This makes an external API call to http://ipinfo.io |  | ||||||
| 	'account_change_character_name' => false, // can user change their character name for premium points? |  | ||||||
| 	'account_change_character_name_points' => 30, // cost of name change |  | ||||||
| 	'account_change_character_sex' => false, // can user change their character sex for premium points? |  | ||||||
| 	'account_change_character_sex_points' => 30, // cost of sex change |  | ||||||
| 	'characters_per_account' => 10,	// max. number of characters per account |  | ||||||
|  |  | ||||||
| 	// mail |  | ||||||
| 	'mail_enabled' => false, // is aac maker configured to send e-mails? |  | ||||||
| 	'mail_address' => 'no-reply@your-server.org', // server e-mail address (from:) |  | ||||||
| 	'mail_admin' => 'your-address@your-server.org', // admin email address, where mails from contact form will be sent |  | ||||||
| 	'mail_signature' => array( // signature that will be included at the end of every message sent using _mail function |  | ||||||
| 		'plain' => ''/*'--\nMy Server,\nhttp://www.myserver.com'*/, |  | ||||||
| 		'html' => ''/*'<br/>My Server,\n<a href="http://www.myserver.com">myserver.com</a>'*/ |  | ||||||
| 	), |  | ||||||
| 	'smtp_enabled' => false, // send by smtp or mail function (set false if use mail function) |  | ||||||
| 	'smtp_host' => '', // mail host |  | ||||||
| 	'smtp_port' => 25, // 25 (default) / 465 (ssl, e.g. gmail) |  | ||||||
| 	'smtp_auth' => true, // need authorization? |  | ||||||
| 	'smtp_user' => 'admin@example.org', |  | ||||||
| 	'smtp_pass' => '', |  | ||||||
|  |  | ||||||
| 	// reCAPTCHA (prevent spam bots) |  | ||||||
| 	'recaptcha_enabled' => false, // enable recaptcha verification code |  | ||||||
| 	'recaptcha_site_key' => '', // get your own site and secret keys at https://www.google.com/recaptcha |  | ||||||
| 	'recaptcha_secret_key' => '', |  | ||||||
| 	'recaptcha_theme' => 'light', // light, dark |  | ||||||
|  |  | ||||||
| 	// |  | ||||||
| 	'generate_new_reckey' => true,				// let player generate new recovery key, he will receive e-mail with new rec key (not display on page, hacker can't generate rec key) |  | ||||||
| 	'generate_new_reckey_price' => 20,			// price for new recovery key |  | ||||||
| 	'send_mail_when_change_password' => true,	// send e-mail with new password when change password to account |  | ||||||
| 	'send_mail_when_generate_reckey' => true,	// send e-mail with rec key (key is displayed on page anyway when generate) |  | ||||||
|  |  | ||||||
| 	// genders (aka sex) |  | ||||||
| 	'genders' => array( |  | ||||||
| 		0 => 'Female', |  | ||||||
| 		1 => 'Male' |  | ||||||
| 	), |  | ||||||
| 	 |  | ||||||
| 	// new character config |  | ||||||
| 	'character_samples' => array( // vocations, format: ID_of_vocation => 'Name of Character to copy' |  | ||||||
| 		//0 => 'Rook Sample', |  | ||||||
| 		1 => 'Sorcerer Sample', |  | ||||||
| 		2 => 'Druid Sample', |  | ||||||
| 		3 => 'Paladin Sample', |  | ||||||
| 		4 => 'Knight Sample' |  | ||||||
| 	), |  | ||||||
|  |  | ||||||
| 	// town list used when creating character |  | ||||||
| 	// won't be displayed if there is only one item (rookgaard for example) |  | ||||||
| 	'character_towns' => array(1), |  | ||||||
|  |  | ||||||
| 	// list of towns |  | ||||||
| 	'towns' => array( |  | ||||||
| 		0 => 'No town', |  | ||||||
| 		1 => 'Sample town' |  | ||||||
| 	), |  | ||||||
|  |  | ||||||
| 	// guilds |  | ||||||
| 	'guild_management' => true, // enable guild management system on the site? |  | ||||||
| 	'guild_need_level' => 1, // min. level to form a guild |  | ||||||
| 	'guild_need_premium' => true, // require premium account to form a guild? |  | ||||||
| 	'guild_image_size_kb' => 80, // maximum size of the guild logo image in KB (kilobytes) |  | ||||||
| 	'guild_description_chars_limit' => 1000, // limit of guild description |  | ||||||
| 	'guild_description_lines_limit' => 6, // limit of lines, if description has more lines it will be showed as long text, without 'enters' |  | ||||||
| 	'guild_motd_chars_limit' => 150, // limit of MOTD (message of the day) that is shown later in the game on the guild channel |  | ||||||
|  |  | ||||||
| 	'quests' => array(), // quests list (displayed in character view), name => storage |  | ||||||
|  |  | ||||||
| 	'signature_enabled' => true, |  | ||||||
| 	'signature_type' => 'tibian', // signature engine to use: tibian, mango, gesior |  | ||||||
| 	'signature_cache_time' => 5, // how long to store cached file (in minutes), default 5 minutes |  | ||||||
| 	'signature_browser_cache' => 60, // how long to cache by browser (in minutes), default 1 hour |  | ||||||
|  |  | ||||||
| 	// online page |  | ||||||
| 	'online_record' => true, // display players record? |  | ||||||
| 	'online_vocations' => false, // display vocation statistics? |  | ||||||
| 	'online_vocations_images' => false, // display vocation images? |  | ||||||
| 	'online_skulls' => false, // display skull images |  | ||||||
| 	'online_outfit' => true, |  | ||||||
| 	'online_afk' => false, |  | ||||||
|  |  | ||||||
| 	// support list page |  | ||||||
| 	'team_style' => 2, // 1/2 (1 - normal table, 2 - in boxes, grouped by group id) |  | ||||||
| 	'team_display_status' => true, |  | ||||||
| 	'team_display_lastlogin' => true, |  | ||||||
| 	'team_display_world' => false, |  | ||||||
|  |  | ||||||
| 	// bans page |  | ||||||
| 	'bans_limit' => 50, |  | ||||||
| 	'bans_display_all' => true, // should all bans be displayed? (sorted page by page) |  | ||||||
|  |  | ||||||
| 	// highscores page |  | ||||||
| 	'highscores_vocation_box' => true, // show 'Choose a vocation' box on the highscores (allowing peoples to sort highscores by vocation)? |  | ||||||
| 	'highscores_vocation' => true, // show player vocation under his nickname? |  | ||||||
| 	'highscores_frags' => false, // show 'Frags' tab (best fraggers on the server)? Only 0.3 |  | ||||||
| 	'highscores_outfit' => true, // show player outfit? |  | ||||||
| 	'highscores_country_box' => false, // doesnt work yet! (not implemented) |  | ||||||
| 	'highscores_groups_hidden' => 4, // this group id and higher won't be shown on the highscores |  | ||||||
| 	'highscores_ids_hidden' => array(0), // this ids of players will be hidden on the highscores (should be ids of samples) |  | ||||||
| 	'highscores_length' => 100, // how many records per page on highscores |  | ||||||
|  |  | ||||||
| 	// characters page |  | ||||||
| 	'characters' => array( // what things to display on character view page (true/false in each option) |  | ||||||
| 		'level' => true, |  | ||||||
| 		'experience' => false, |  | ||||||
| 		'magic_level' => false, |  | ||||||
| 		'balance' => false, |  | ||||||
| 		'marriage_info' => true, // only 0.3 |  | ||||||
| 		'outfit' => true, |  | ||||||
| 		'creation_date' => true, |  | ||||||
| 		'quests' => true, |  | ||||||
| 		'skills' => true, |  | ||||||
| 		'equipment' => true, |  | ||||||
| 		'frags' => false |  | ||||||
| 	), |  | ||||||
|  |  | ||||||
| 	// news page |  | ||||||
| 	'news_limit' => 5, // limit of news on the latest news page |  | ||||||
| 	'news_ticker_limit' => 5, // limit of news in tickers (mini news) (0 to disable) |  | ||||||
| 	'news_date_format' => 'j.n.Y', // check php manual date() function for more info about this |  | ||||||
| 	'news_author' => true, // show author of the news |  | ||||||
|  |  | ||||||
| 	// gifts/shop system |  | ||||||
| 	'gifts_system' => false, |  | ||||||
| 	 |  | ||||||
| 	// support/system |  | ||||||
| 	'bug_report' => true, // this configurable has no effect, its always enabled |  | ||||||
| 	 |  | ||||||
| 	// forum |  | ||||||
| 	'forum' => 'site', // link to the server forum, set to "site" if you want to use build in forum system, otherwise leave empty if you aren't going to use any forum |  | ||||||
| 	'forum_level_required' => 0, // level required to post, 0 to disable |  | ||||||
| 	'forum_post_interval' => 30, // in seconds |  | ||||||
| 	'forum_posts_per_page' => 20, |  | ||||||
| 	'forum_threads_per_page' => 20, |  | ||||||
|  |  | ||||||
| 	// last kills |  | ||||||
| 	'last_kills_limit' => 50, // max. number of deaths shown on the last kills page |  | ||||||
|  |  | ||||||
| 	// status, took automatically from config file if empty |  | ||||||
| 	'status_ip' => '', |  | ||||||
| 	'status_port' => '', |  | ||||||
|  |  | ||||||
| 	// other |  | ||||||
| 	'anonymous_usage_statistics' => true, |  | ||||||
| 	'email_lai_sec_interval' => 60, // time in seconds between e-mails to one account from lost account interface, block spam |  | ||||||
| 	'google_analytics_id' => '', // e.g.: UA-XXXXXXX-X |  | ||||||
| 	'experiencetable_columns' => 5, // how many columns to display in experience table page. * experiencetable_rows, 5 = 500 (will show up to 500 level) |  | ||||||
| 	'experiencetable_rows' => 100, // till how many levels in one column |  | ||||||
| 	'date_timezone' => 'Europe/Berlin', // more info at http://php.net/manual/en/timezones.php |  | ||||||
| 	 |  | ||||||
| 	'monsters' => array(), |  | ||||||
| 	'npc' => array() |  | ||||||
| ); |  | ||||||
|  |  | ||||||
| // download link to client. |  | ||||||
| $config['client_download'] = 'http://tibia-clients.com/clients/download/'. $config['client'] .'/exe/windows'; |  | ||||||
| $config['client_download_linux'] = 'http://tibia-clients.com/clients/download/'. $config['client'] .'/tar/linux'; |  | ||||||
|  |  | ||||||
| ?> |  | ||||||
							
								
								
									
										9
									
								
								cypress.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,9 @@ | |||||||
|  | const { defineConfig } = require("cypress"); | ||||||
|  |  | ||||||
|  | module.exports = defineConfig({ | ||||||
|  |   e2e: { | ||||||
|  |     setupNodeEvents(on, config) { | ||||||
|  |       // implement node event listeners here | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | }); | ||||||
							
								
								
									
										76
									
								
								cypress/e2e/1-install.cy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,76 @@ | |||||||
|  | describe('Install MyAAC', () => { | ||||||
|  | 	beforeEach(() => { | ||||||
|  | 		// Cypress starts out with a blank slate for each test | ||||||
|  | 		// so we must tell it to visit our website with the `cy.visit()` command. | ||||||
|  | 		// Since we want to visit the same URL at the start of all our tests, | ||||||
|  | 		// we include it in our beforeEach function so that it runs before each test | ||||||
|  | 		cy.visit(Cypress.env('URL')) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go through installer', () => { | ||||||
|  | 		cy.visit(Cypress.env('URL') + '/install/?step=welcome') | ||||||
|  | 		cy.wait(1000) | ||||||
|  |  | ||||||
|  | 		cy.screenshot('install-welcome') | ||||||
|  |  | ||||||
|  | 		// step 1 - Welcome | ||||||
|  | 		cy.get('select[name="lang"]').select('en') | ||||||
|  |  | ||||||
|  | 		//cy.get('input[type=button]').contains('Next »').click() | ||||||
|  |  | ||||||
|  | 		cy.get('form').submit() | ||||||
|  |  | ||||||
|  | 		// step 2 - License | ||||||
|  | 		// just skip | ||||||
|  | 		cy.contains('GNU/GPL License'); | ||||||
|  | 		cy.get('form').submit() | ||||||
|  |  | ||||||
|  | 		// step 3 - Requirements | ||||||
|  | 		cy.contains('Requirements check'); | ||||||
|  |  | ||||||
|  | 		cy.get('#step').then(elem => { | ||||||
|  | 			elem.val('config'); | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		cy.get('form').submit() | ||||||
|  |  | ||||||
|  | 		// step 4 - Configuration | ||||||
|  | 		cy.contains('Basic configuration'); | ||||||
|  |  | ||||||
|  | 		cy.get('#vars_server_path').click().clear().type(Cypress.env('SERVER_PATH')) | ||||||
|  |  | ||||||
|  | 		cy.get('[type="checkbox"]').uncheck() // usage statistics uncheck | ||||||
|  |  | ||||||
|  | 		cy.wait(1000) | ||||||
|  |  | ||||||
|  | 		cy.get('form').submit() | ||||||
|  |  | ||||||
|  | 		// check if there is any error | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		// step 5 - Import Schema | ||||||
|  | 		cy.contains('Import MySQL schema'); | ||||||
|  |  | ||||||
|  | 		// AAC is not installed yet, this message should not come | ||||||
|  | 		cy.contains('Seems AAC is already installed. Skipping importing MySQL schema..').should('not.exist') | ||||||
|  |  | ||||||
|  | 		cy.contains('[class="alert alert-success"]', 'Local configuration has been saved into file: config.local.php').should('be.visible') | ||||||
|  |  | ||||||
|  | 		cy.get('form').submit() | ||||||
|  |  | ||||||
|  | 		// step 6 - Admin Account | ||||||
|  | 		cy.get('#vars_email').click().clear().type('admin@my-aac.org') | ||||||
|  | 		cy.get('#vars_account').click().clear().type('admin') | ||||||
|  | 		cy.get('#vars_password').click().clear().type('test1234') | ||||||
|  | 		cy.get('#vars_password_confirm').click().clear().type('test1234') | ||||||
|  | 		cy.get('#vars_player_name').click().clear().type('Admin') | ||||||
|  |  | ||||||
|  | 		cy.get('form').submit() | ||||||
|  |  | ||||||
|  | 		cy.contains('[class="alert alert-success"]', 'Congratulations', { timeout: 60000 }).should('be.visible') | ||||||
|  |  | ||||||
|  | 		cy.wait(2000); | ||||||
|  |  | ||||||
|  | 		cy.screenshot('install-finish') | ||||||
|  | 	}) | ||||||
|  | }) | ||||||
							
								
								
									
										33
									
								
								cypress/e2e/2-create-account.cy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,33 @@ | |||||||
|  | describe('Create Account Page', () => { | ||||||
|  | 	beforeEach(() => { | ||||||
|  | 		// Cypress starts out with a blank slate for each test | ||||||
|  | 		// so we must tell it to visit our website with the `cy.visit()` command. | ||||||
|  | 		// Since we want to visit the same URL at the start of all our tests, | ||||||
|  | 		// we include it in our beforeEach function so that it runs before each test | ||||||
|  | 		cy.visit(Cypress.env('URL') + '/index.php/account/create') | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Create Test Account', () => { | ||||||
|  | 		cy.screenshot('create-account-page') | ||||||
|  |  | ||||||
|  | 		cy.get('#account_input').type('tester') | ||||||
|  | 		cy.get('#email').type('tester@example.com') | ||||||
|  |  | ||||||
|  | 		cy.get('#password').type('test1234') | ||||||
|  | 		cy.get('#password_confirm').type('test1234') | ||||||
|  |  | ||||||
|  | 		cy.get('#character_name').type('Slaw') | ||||||
|  |  | ||||||
|  | 		cy.get('#sex1').check() | ||||||
|  | 		cy.get('#vocation1').check() | ||||||
|  | 		cy.get('#accept_rules').check() | ||||||
|  |  | ||||||
|  | 		cy.get('#createaccount').submit() | ||||||
|  |  | ||||||
|  | 		// no errors please | ||||||
|  | 		cy.contains('The Following Errors Have Occurred:').should('not.exist') | ||||||
|  |  | ||||||
|  | 		// ss of post page | ||||||
|  | 		cy.screenshot('create-account-page-post') | ||||||
|  | 	}) | ||||||
|  | }) | ||||||
							
								
								
									
										174
									
								
								cypress/e2e/3-check-public-pages.cy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,174 @@ | |||||||
|  | describe('Check Public Pages', () => { | ||||||
|  |  | ||||||
|  | 	/// news | ||||||
|  | 	it('Go to news page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/news', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to news archive page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/news/archive', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to changelog page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/change-log', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	/// account management | ||||||
|  | 	it('Go to account manage page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/account/manage', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to account create page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/account/create', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to account lost page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/account/lost', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to rules page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/rules', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	// community | ||||||
|  | 	it('Go to online page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/online', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to characters list page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/characters', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to guilds page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/guilds', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to highscores page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/highscores', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to last kills page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/last-kills', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to houses page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/houses', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to bans page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/bans', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to forum page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/forum', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to team page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/team', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	// library | ||||||
|  | 	it('Go to monsters page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/monsters', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to spells page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/spells', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to server info page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/ots-info', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to commands page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/commands', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to downloads page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/downloads', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to gallery page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/gallery', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to experience table page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/exp-table', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to faq page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/faq', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  | }) | ||||||
							
								
								
									
										81
									
								
								cypress/e2e/4-check-protected-pages.cy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,81 @@ | |||||||
|  | const REQUIRED_LOGIN_MESSAGE = 'Please enter your account name and your password.'; | ||||||
|  | const YOU_ARE_NOT_LOGGEDIN = 'You are not logged in.'; | ||||||
|  |  | ||||||
|  | describe('Check Protected Pages', () => { | ||||||
|  |  | ||||||
|  | 	// character actions | ||||||
|  | 	it('Go to account character creation page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/account/character/create', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 		cy.contains(REQUIRED_LOGIN_MESSAGE) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to account character deletion page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/account/character/delete', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 		cy.contains(REQUIRED_LOGIN_MESSAGE) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	// account actions | ||||||
|  | 	it('Go to account email change page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/account/email', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 		cy.contains(REQUIRED_LOGIN_MESSAGE) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to account password change page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/account/password', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 		cy.contains(REQUIRED_LOGIN_MESSAGE) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to account info change page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/account/info', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 		cy.contains(REQUIRED_LOGIN_MESSAGE) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to account logout change page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/account/logout', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 		cy.contains(REQUIRED_LOGIN_MESSAGE) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	// guild actions | ||||||
|  | 	it('Go to guild creation page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/?subtopic=guilds&action=create', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 		cy.contains(YOU_ARE_NOT_LOGGEDIN) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to guilds cleanup players action page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/?subtopic=guilds&action=cleanup_players', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 		cy.contains(YOU_ARE_NOT_LOGGEDIN) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	it('Go to guilds cleanup guilds action page', () => { | ||||||
|  | 		cy.visit({ | ||||||
|  | 			url: Cypress.env('URL') + '/?subtopic=guilds&action=cleanup_guilds', | ||||||
|  | 			method: 'GET', | ||||||
|  | 		}) | ||||||
|  | 		cy.contains(YOU_ARE_NOT_LOGGEDIN) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | }) | ||||||
							
								
								
									
										5
									
								
								cypress/fixtures/example.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,5 @@ | |||||||
|  | { | ||||||
|  |   "name": "Using fixtures to represent data", | ||||||
|  |   "email": "hello@cypress.io", | ||||||
|  |   "body": "Fixtures are a great way to mock data for responses to routes" | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								cypress/support/commands.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,25 @@ | |||||||
|  | // *********************************************** | ||||||
|  | // This example commands.js shows you how to | ||||||
|  | // create various custom commands and overwrite | ||||||
|  | // existing commands. | ||||||
|  | // | ||||||
|  | // For more comprehensive examples of custom | ||||||
|  | // commands please read more here: | ||||||
|  | // https://on.cypress.io/custom-commands | ||||||
|  | // *********************************************** | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // -- This is a parent command -- | ||||||
|  | // Cypress.Commands.add('login', (email, password) => { ... }) | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // -- This is a child command -- | ||||||
|  | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // -- This is a dual command -- | ||||||
|  | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) | ||||||
|  | // | ||||||
|  | // | ||||||
|  | // -- This will overwrite an existing command -- | ||||||
|  | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) | ||||||
							
								
								
									
										20
									
								
								cypress/support/e2e.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,20 @@ | |||||||
|  | // *********************************************************** | ||||||
|  | // This example support/e2e.js is processed and | ||||||
|  | // loaded automatically before your test files. | ||||||
|  | // | ||||||
|  | // This is a great place to put global configuration and | ||||||
|  | // behavior that modifies Cypress. | ||||||
|  | // | ||||||
|  | // You can change the location of this file or turn off | ||||||
|  | // automatically serving support files with the | ||||||
|  | // 'supportFile' configuration option. | ||||||
|  | // | ||||||
|  | // You can read more here: | ||||||
|  | // https://on.cypress.io/configuration | ||||||
|  | // *********************************************************** | ||||||
|  |  | ||||||
|  | // Import commands.js using ES2015 syntax: | ||||||
|  | import './commands' | ||||||
|  |  | ||||||
|  | // Alternatively you can use CommonJS syntax: | ||||||
|  | // require('./commands') | ||||||
							
								
								
									
										
											BIN
										
									
								
								images/del.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 433 B After Width: | Height: | Size: 318 B | 
							
								
								
									
										
											BIN
										
									
								
								images/druid.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 10 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/edit.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 363 B | 
							
								
								
									
										0
									
								
								images/editor/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								images/error.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/error.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 706 B After Width: | Height: | Size: 592 B | 
							
								
								
									
										
											BIN
										
									
								
								images/false.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 1004 B After Width: | Height: | Size: 845 B | 
							
								
								
									
										0
									
								
								images/gallery/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								images/hist.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 117 B After Width: | Height: | Size: 110 B | 
							
								
								
									
										
											BIN
										
									
								
								images/icons/comment_add.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 530 B | 
							
								
								
									
										
											BIN
										
									
								
								images/info.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 783 B After Width: | Height: | Size: 631 B | 
| Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 12 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/loading_spinner.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 67 KiB | 
| Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.8 KiB | 
| Before Width: | Height: | Size: 1.5 KiB |