" . $ban["uid"] . "
");
+ } else if ($ban["name"]) {
+ $name = (string)$ban["name"];
+ } else if ($ban["ip"]) {
+ $ip = str_replace("\\", "", (string) $ban["ip"]);
+
+ try {
+ $name = Utils::censorIpAddress($ip);
+ } catch (\Exception $e) {}
+
+ if ($ip === Utils::getClientIp()) {
+ $ipbanned = [
+ "invoker" => (string)$ban["invokername"],
+ "reason" => (string)$ban["reason"]
+ ];
+ }
+ }
+
+ $data[] = [
+ "name" => $name,
+ "reason" => (string)$ban["reason"],
+ "invoker" => (string)$ban["invokername"],
+ "created" => $ban["created"],
+ "duration" => $ban["duration"]
+ ];
+ }
+}
+
+TemplateUtils::i()->renderTemplate("bans", [
+ "banlist" => $data,
+ "ipbanned" => $ipbanned
+]);
diff --git a/src/composer.json b/src/composer.json
new file mode 100644
index 0000000..318ad8f
--- /dev/null
+++ b/src/composer.json
@@ -0,0 +1,24 @@
+{
+ "config": {
+ "vendor-dir": "private/vendor"
+ },
+ "require": {
+ "roave/security-advisories": "dev-master",
+ "php": ">=5.6.0",
+ "ext-mbstring": "*",
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "planetteamspeak/ts3-php-framework": "1.1.32",
+ "latte/latte": "^2.4",
+ "wruczek/php-file-cache": "^0",
+ "simplepie/simplepie": "^1.5",
+ "catfan/medoo": "^1.5"
+ },
+ "suggest": {
+ "ext-pdo_mysql": "*",
+ "ext-pdo_sqlite": "*"
+ },
+ "autoload": {
+ "psr-4": {"Wruczek\\TSWebsite\\": "private/php"}
+ }
+}
diff --git a/src/css/cookiealert.css b/src/css/cookiealert.css
new file mode 100644
index 0000000..7260ad6
--- /dev/null
+++ b/src/css/cookiealert.css
@@ -0,0 +1,29 @@
+.cookiealert {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ margin: 0 !important;
+ z-index: 999;
+ opacity: 0;
+ border-radius: 0;
+ background: #212327 url("../img/cubes.png");
+ transform: translateY(100%);
+ transition: all 500ms ease-out;
+ color: #ecf0f1;
+}
+
+.cookiealert.show {
+ opacity: 1;
+ transform: translateY(0%);
+ transition-delay: 1000ms;
+}
+
+.cookiealert a {
+ text-decoration: underline
+}
+
+.cookiealert .acceptcookies {
+ margin-left: 10px;
+ vertical-align: baseline;
+}
diff --git a/src/css/dev.css b/src/css/dev.css
new file mode 100644
index 0000000..cddfcec
--- /dev/null
+++ b/src/css/dev.css
@@ -0,0 +1,10 @@
+/* FOR DEVELOPMENT */
+
+.xdebug-var-dump {
+ background: #fff;
+ padding: 15px;
+}
+
+debug-step {
+ display: none;
+}
diff --git a/src/css/flags/famfamfam-flags.min.css b/src/css/flags/famfamfam-flags.min.css
new file mode 100644
index 0000000..d39f81e
--- /dev/null
+++ b/src/css/flags/famfamfam-flags.min.css
@@ -0,0 +1 @@
+.famfamfam-flags{background:url(famfamfam-flags.png) no-repeat;display: inline-block;background-size:224px 199px}.famfamfam-flags.me{width:16px;height:12px;background-position:0 0}.famfamfam-flags.ky{width:16px;height:11px;background-position:-16px 0}.famfamfam-flags.af{width:16px;height:11px;background-position:0 -12px}.famfamfam-flags.ag{width:16px;height:11px;background-position:-16px -12px}.famfamfam-flags.ai{width:16px;height:11px;background-position:-32px 0}.famfamfam-flags.al{width:16px;height:11px;background-position:-32px -11px}.famfamfam-flags.am{width:16px;height:11px;background-position:0 -23px}.famfamfam-flags.an{width:16px;height:11px;background-position:-16px -23px}.famfamfam-flags.ao{width:16px;height:11px;background-position:-32px -23px}.famfamfam-flags.ar{width:16px;height:11px;background-position:0 -34px}.famfamfam-flags.as{width:16px;height:11px;background-position:-16px -34px}.famfamfam-flags.at{width:16px;height:11px;background-position:-32px -34px}.famfamfam-flags.au{width:16px;height:11px;background-position:-48px 0}.famfamfam-flags.aw{width:16px;height:11px;background-position:-48px -11px}.famfamfam-flags.ax{width:16px;height:11px;background-position:-48px -22px}.famfamfam-flags.az{width:16px;height:11px;background-position:-48px -33px}.famfamfam-flags.ba{width:16px;height:11px;background-position:0 -45px}.famfamfam-flags.bb{width:16px;height:11px;background-position:-16px -45px}.famfamfam-flags.bd{width:16px;height:11px;background-position:-32px -45px}.famfamfam-flags.be{width:16px;height:11px;background-position:-48px -45px}.famfamfam-flags.bf{width:16px;height:11px;background-position:-64px 0}.famfamfam-flags.bg{width:16px;height:11px;background-position:-64px -11px}.famfamfam-flags.bh{width:16px;height:11px;background-position:-64px -22px}.famfamfam-flags.bi{width:16px;height:11px;background-position:-64px -33px}.famfamfam-flags.bj{width:16px;height:11px;background-position:-64px -44px}.famfamfam-flags.bm{width:16px;height:11px;background-position:0 -56px}.famfamfam-flags.bn{width:16px;height:11px;background-position:-16px -56px}.famfamfam-flags.bo{width:16px;height:11px;background-position:-32px -56px}.famfamfam-flags.br{width:16px;height:11px;background-position:-48px -56px}.famfamfam-flags.bs{width:16px;height:11px;background-position:-64px -56px}.famfamfam-flags.bt{width:16px;height:11px;background-position:0 -67px}.famfamfam-flags.bv{width:16px;height:11px;background-position:-16px -67px}.famfamfam-flags.bw{width:16px;height:11px;background-position:-32px -67px}.famfamfam-flags.by{width:16px;height:11px;background-position:-48px -67px}.famfamfam-flags.bz{width:16px;height:11px;background-position:-64px -67px}.famfamfam-flags.ca{width:16px;height:11px;background-position:-80px 0}.famfamfam-flags.catalonia{width:16px;height:11px;background-position:-80px -11px}.famfamfam-flags.cc{width:16px;height:11px;background-position:-80px -22px}.famfamfam-flags.cd{width:16px;height:11px;background-position:-80px -33px}.famfamfam-flags.cf{width:16px;height:11px;background-position:-80px -44px}.famfamfam-flags.cg{width:16px;height:11px;background-position:-80px -55px}.famfamfam-flags.zm{width:16px;height:11px;background-position:-80px -66px}.famfamfam-flags.ci{width:16px;height:11px;background-position:0 -78px}.famfamfam-flags.ck{width:16px;height:11px;background-position:-16px -78px}.famfamfam-flags.cl{width:16px;height:11px;background-position:-32px -78px}.famfamfam-flags.cm{width:16px;height:11px;background-position:-48px -78px}.famfamfam-flags.cn{width:16px;height:11px;background-position:-64px -78px}.famfamfam-flags.co{width:16px;height:11px;background-position:-80px -78px}.famfamfam-flags.cr{width:16px;height:11px;background-position:-96px 0}.famfamfam-flags.cs{width:16px;height:11px;background-position:-96px -11px}.famfamfam-flags.cu{width:16px;height:11px;background-position:-96px -22px}.famfamfam-flags.cv{width:16px;height:11px;background-position:-96px -33px}.famfamfam-flags.cx{width:16px;height:11px;background-position:-96px -44px}.famfamfam-flags.cy{width:16px;height:11px;background-position:-96px -55px}.famfamfam-flags.cz{width:16px;height:11px;background-position:-96px -66px}.famfamfam-flags.de{width:16px;height:11px;background-position:-96px -77px}.famfamfam-flags.dj{width:16px;height:11px;background-position:0 -89px}.famfamfam-flags.dk{width:16px;height:11px;background-position:-16px -89px}.famfamfam-flags.dm{width:16px;height:11px;background-position:-32px -89px}.famfamfam-flags.do{width:16px;height:11px;background-position:-48px -89px}.famfamfam-flags.dz{width:16px;height:11px;background-position:-64px -89px}.famfamfam-flags.ec{width:16px;height:11px;background-position:-80px -89px}.famfamfam-flags.ee{width:16px;height:11px;background-position:-96px -89px}.famfamfam-flags.eg{width:16px;height:11px;background-position:0 -100px}.famfamfam-flags.eh{width:16px;height:11px;background-position:-16px -100px}.famfamfam-flags.england{width:16px;height:11px;background-position:-32px -100px}.famfamfam-flags.er{width:16px;height:11px;background-position:-48px -100px}.famfamfam-flags.es{width:16px;height:11px;background-position:-64px -100px}.famfamfam-flags.et{width:16px;height:11px;background-position:-80px -100px}.famfamfam-flags.europeanunion{width:16px;height:11px;background-position:-96px -100px}.famfamfam-flags.fam{width:16px;height:11px;background-position:-112px 0}.famfamfam-flags.fi{width:16px;height:11px;background-position:-112px -11px}.famfamfam-flags.fj{width:16px;height:11px;background-position:-112px -22px}.famfamfam-flags.fk{width:16px;height:11px;background-position:-112px -33px}.famfamfam-flags.fm{width:16px;height:11px;background-position:-112px -44px}.famfamfam-flags.fo{width:16px;height:11px;background-position:-112px -55px}.famfamfam-flags.fr,.famfamfam-flags.gp,.famfamfam-flags.mf,.famfamfam-flags.re,.famfamfam-flags.yt{width:16px;height:11px;background-position:-112px -66px}.famfamfam-flags.ga{width:16px;height:11px;background-position:-112px -77px}.famfamfam-flags.gb{width:16px;height:11px;background-position:-112px -88px}.famfamfam-flags.gd{width:16px;height:11px;background-position:-112px -99px}.famfamfam-flags.ge{width:16px;height:11px;background-position:0 -111px}.famfamfam-flags.gf{width:16px;height:11px;background-position:-16px -111px}.famfamfam-flags.gg{width:16px;height:11px;background-position:-32px -111px}.famfamfam-flags.gh{width:16px;height:11px;background-position:-48px -111px}.famfamfam-flags.gi{width:16px;height:11px;background-position:-64px -111px}.famfamfam-flags.gl{width:16px;height:11px;background-position:-80px -111px}.famfamfam-flags.gm{width:16px;height:11px;background-position:-96px -111px}.famfamfam-flags.gn{width:16px;height:11px;background-position:-112px -111px}.famfamfam-flags.gp{width:16px;height:11px;background-position:-128px 0}.famfamfam-flags.gq{width:16px;height:11px;background-position:-128px -11px}.famfamfam-flags.gr{width:16px;height:11px;background-position:-128px -22px}.famfamfam-flags.gs{width:16px;height:11px;background-position:-128px -33px}.famfamfam-flags.gt{width:16px;height:11px;background-position:-128px -44px}.famfamfam-flags.gu{width:16px;height:11px;background-position:-128px -55px}.famfamfam-flags.gw{width:16px;height:11px;background-position:-128px -66px}.famfamfam-flags.gy{width:16px;height:11px;background-position:-128px -77px}.famfamfam-flags.hk{width:16px;height:11px;background-position:-128px -88px}.famfamfam-flags.hm{width:16px;height:11px;background-position:-128px -99px}.famfamfam-flags.hn{width:16px;height:11px;background-position:-128px -110px}.famfamfam-flags.hr{width:16px;height:11px;background-position:0 -122px}.famfamfam-flags.ht{width:16px;height:11px;background-position:-16px -122px}.famfamfam-flags.hu{width:16px;height:11px;background-position:-32px -122px}.famfamfam-flags.id{width:16px;height:11px;background-position:-48px -122px}.famfamfam-flags.ie{width:16px;height:11px;background-position:-64px -122px}.famfamfam-flags.il{width:16px;height:11px;background-position:-80px -122px}.famfamfam-flags.in{width:16px;height:11px;background-position:-96px -122px}.famfamfam-flags.io{width:16px;height:11px;background-position:-112px -122px}.famfamfam-flags.iq{width:16px;height:11px;background-position:-128px -122px}.famfamfam-flags.ir{width:16px;height:11px;background-position:0 -133px}.famfamfam-flags.is{width:16px;height:11px;background-position:-16px -133px}.famfamfam-flags.it{width:16px;height:11px;background-position:-32px -133px}.famfamfam-flags.je{width:16px;height:11px;background-position:-48px -133px}.famfamfam-flags.jm{width:16px;height:11px;background-position:-64px -133px}.famfamfam-flags.jo{width:16px;height:11px;background-position:-80px -133px}.famfamfam-flags.jp{width:16px;height:11px;background-position:-96px -133px}.famfamfam-flags.ke{width:16px;height:11px;background-position:-112px -133px}.famfamfam-flags.kg{width:16px;height:11px;background-position:-128px -133px}.famfamfam-flags.kh{width:16px;height:11px;background-position:-144px 0}.famfamfam-flags.ki{width:16px;height:11px;background-position:-144px -11px}.famfamfam-flags.km{width:16px;height:11px;background-position:-144px -22px}.famfamfam-flags.kn{width:16px;height:11px;background-position:-144px -33px}.famfamfam-flags.kp{width:16px;height:11px;background-position:-144px -44px}.famfamfam-flags.kr{width:16px;height:11px;background-position:-144px -55px}.famfamfam-flags.kw{width:16px;height:11px;background-position:-144px -66px}.famfamfam-flags.ae{width:16px;height:11px;background-position:-144px -77px}.famfamfam-flags.kz{width:16px;height:11px;background-position:-144px -88px}.famfamfam-flags.la{width:16px;height:11px;background-position:-144px -99px}.famfamfam-flags.lb{width:16px;height:11px;background-position:-144px -110px}.famfamfam-flags.lc{width:16px;height:11px;background-position:-144px -121px}.famfamfam-flags.li{width:16px;height:11px;background-position:-144px -132px}.famfamfam-flags.lk{width:16px;height:11px;background-position:0 -144px}.famfamfam-flags.lr{width:16px;height:11px;background-position:-16px -144px}.famfamfam-flags.ls{width:16px;height:11px;background-position:-32px -144px}.famfamfam-flags.lt{width:16px;height:11px;background-position:-48px -144px}.famfamfam-flags.lu{width:16px;height:11px;background-position:-64px -144px}.famfamfam-flags.lv{width:16px;height:11px;background-position:-80px -144px}.famfamfam-flags.ly{width:16px;height:11px;background-position:-96px -144px}.famfamfam-flags.ma{width:16px;height:11px;background-position:-112px -144px}.famfamfam-flags.mc{width:16px;height:11px;background-position:-128px -144px}.famfamfam-flags.md{width:16px;height:11px;background-position:-144px -144px}.famfamfam-flags.ad{width:16px;height:11px;background-position:-160px 0}.famfamfam-flags.mg{width:16px;height:11px;background-position:-160px -11px}.famfamfam-flags.mh{width:16px;height:11px;background-position:-160px -22px}.famfamfam-flags.mk{width:16px;height:11px;background-position:-160px -33px}.famfamfam-flags.ml{width:16px;height:11px;background-position:-160px -44px}.famfamfam-flags.mm{width:16px;height:11px;background-position:-160px -55px}.famfamfam-flags.mn{width:16px;height:11px;background-position:-160px -66px}.famfamfam-flags.mo{width:16px;height:11px;background-position:-160px -77px}.famfamfam-flags.mp{width:16px;height:11px;background-position:-160px -88px}.famfamfam-flags.mq{width:16px;height:11px;background-position:-160px -99px}.famfamfam-flags.mr{width:16px;height:11px;background-position:-160px -110px}.famfamfam-flags.ms{width:16px;height:11px;background-position:-160px -121px}.famfamfam-flags.mt{width:16px;height:11px;background-position:-160px -132px}.famfamfam-flags.mu{width:16px;height:11px;background-position:-160px -143px}.famfamfam-flags.mv{width:16px;height:11px;background-position:0 -155px}.famfamfam-flags.mw{width:16px;height:11px;background-position:-16px -155px}.famfamfam-flags.mx{width:16px;height:11px;background-position:-32px -155px}.famfamfam-flags.my{width:16px;height:11px;background-position:-48px -155px}.famfamfam-flags.mz{width:16px;height:11px;background-position:-64px -155px}.famfamfam-flags.na{width:16px;height:11px;background-position:-80px -155px}.famfamfam-flags.nc{width:16px;height:11px;background-position:-96px -155px}.famfamfam-flags.ne{width:16px;height:11px;background-position:-112px -155px}.famfamfam-flags.nf{width:16px;height:11px;background-position:-128px -155px}.famfamfam-flags.ng{width:16px;height:11px;background-position:-144px -155px}.famfamfam-flags.ni{width:16px;height:11px;background-position:-160px -155px}.famfamfam-flags.bq,.famfamfam-flags.nl{width:16px;height:11px;background-position:-176px 0}.famfamfam-flags.no{width:16px;height:11px;background-position:-176px -11px}.famfamfam-flags.za{width:16px;height:11px;background-position:-176px -22px}.famfamfam-flags.nr{width:16px;height:11px;background-position:-176px -33px}.famfamfam-flags.nu{width:16px;height:11px;background-position:-176px -44px}.famfamfam-flags.nz{width:16px;height:11px;background-position:-176px -55px}.famfamfam-flags.om{width:16px;height:11px;background-position:-176px -66px}.famfamfam-flags.pa{width:16px;height:11px;background-position:-176px -77px}.famfamfam-flags.pe{width:16px;height:11px;background-position:-176px -88px}.famfamfam-flags.pf{width:16px;height:11px;background-position:-176px -99px}.famfamfam-flags.pg{width:16px;height:11px;background-position:-176px -110px}.famfamfam-flags.ph{width:16px;height:11px;background-position:-176px -121px}.famfamfam-flags.pk{width:16px;height:11px;background-position:-176px -132px}.famfamfam-flags.pl{width:16px;height:11px;background-position:-176px -143px}.famfamfam-flags.pm{width:16px;height:11px;background-position:-176px -154px}.famfamfam-flags.pn{width:16px;height:11px;background-position:0 -166px}.famfamfam-flags.pr{width:16px;height:11px;background-position:-16px -166px}.famfamfam-flags.ps{width:16px;height:11px;background-position:-32px -166px}.famfamfam-flags.pt{width:16px;height:11px;background-position:-48px -166px}.famfamfam-flags.pw{width:16px;height:11px;background-position:-64px -166px}.famfamfam-flags.py{width:16px;height:11px;background-position:-80px -166px}.famfamfam-flags.qa{width:16px;height:11px;background-position:-96px -166px}.famfamfam-flags.re{width:16px;height:11px;background-position:-112px -166px}.famfamfam-flags.ro{width:16px;height:11px;background-position:-128px -166px}.famfamfam-flags.rs{width:16px;height:11px;background-position:-144px -166px}.famfamfam-flags.ru{width:16px;height:11px;background-position:-160px -166px}.famfamfam-flags.rw{width:16px;height:11px;background-position:-176px -166px}.famfamfam-flags.sa{width:16px;height:11px;background-position:0 -177px}.famfamfam-flags.sb{width:16px;height:11px;background-position:-16px -177px}.famfamfam-flags.sc{width:16px;height:11px;background-position:-32px -177px}.famfamfam-flags.scotland{width:16px;height:11px;background-position:-48px -177px}.famfamfam-flags.sd{width:16px;height:11px;background-position:-64px -177px}.famfamfam-flags.se{width:16px;height:11px;background-position:-80px -177px}.famfamfam-flags.sg{width:16px;height:11px;background-position:-96px -177px}.famfamfam-flags.sh{width:16px;height:11px;background-position:-112px -177px}.famfamfam-flags.si{width:16px;height:11px;background-position:-128px -177px}.famfamfam-flags.sj{width:16px;height:11px;background-position:-144px -177px}.famfamfam-flags.sk{width:16px;height:11px;background-position:-160px -177px}.famfamfam-flags.sl{width:16px;height:11px;background-position:-176px -177px}.famfamfam-flags.sm{width:16px;height:11px;background-position:-192px 0}.famfamfam-flags.sn{width:16px;height:11px;background-position:-192px -11px}.famfamfam-flags.so{width:16px;height:11px;background-position:-192px -22px}.famfamfam-flags.sr{width:16px;height:11px;background-position:-192px -33px}.famfamfam-flags.st{width:16px;height:11px;background-position:-192px -44px}.famfamfam-flags.sv{width:16px;height:11px;background-position:-192px -55px}.famfamfam-flags.sy{width:16px;height:11px;background-position:-192px -66px}.famfamfam-flags.sz{width:16px;height:11px;background-position:-192px -77px}.famfamfam-flags.tc{width:16px;height:11px;background-position:-192px -88px}.famfamfam-flags.td{width:16px;height:11px;background-position:-192px -99px}.famfamfam-flags.tf{width:16px;height:11px;background-position:-192px -110px}.famfamfam-flags.tg{width:16px;height:11px;background-position:-192px -121px}.famfamfam-flags.th{width:16px;height:11px;background-position:-192px -132px}.famfamfam-flags.tj{width:16px;height:11px;background-position:-192px -143px}.famfamfam-flags.tk{width:16px;height:11px;background-position:-192px -154px}.famfamfam-flags.tl{width:16px;height:11px;background-position:-192px -165px}.famfamfam-flags.tm{width:16px;height:11px;background-position:-192px -176px}.famfamfam-flags.tn{width:16px;height:11px;background-position:0 -188px}.famfamfam-flags.to{width:16px;height:11px;background-position:-16px -188px}.famfamfam-flags.tr{width:16px;height:11px;background-position:-32px -188px}.famfamfam-flags.tt{width:16px;height:11px;background-position:-48px -188px}.famfamfam-flags.tv{width:16px;height:11px;background-position:-64px -188px}.famfamfam-flags.tw{width:16px;height:11px;background-position:-80px -188px}.famfamfam-flags.tz{width:16px;height:11px;background-position:-96px -188px}.famfamfam-flags.ua{width:16px;height:11px;background-position:-112px -188px}.famfamfam-flags.ug{width:16px;height:11px;background-position:-128px -188px}.famfamfam-flags.um{width:16px;height:11px;background-position:-144px -188px}.famfamfam-flags.us{width:16px;height:11px;background-position:-160px -188px}.famfamfam-flags.uy{width:16px;height:11px;background-position:-176px -188px}.famfamfam-flags.uz{width:16px;height:11px;background-position:-192px -188px}.famfamfam-flags.va{width:16px;height:11px;background-position:-208px 0}.famfamfam-flags.vc{width:16px;height:11px;background-position:-208px -11px}.famfamfam-flags.ve{width:16px;height:11px;background-position:-208px -22px}.famfamfam-flags.vg{width:16px;height:11px;background-position:-208px -33px}.famfamfam-flags.vi{width:16px;height:11px;background-position:-208px -44px}.famfamfam-flags.vn{width:16px;height:11px;background-position:-208px -55px}.famfamfam-flags.vu{width:16px;height:11px;background-position:-208px -66px}.famfamfam-flags.wales{width:16px;height:11px;background-position:-208px -77px}.famfamfam-flags.wf{width:16px;height:11px;background-position:-208px -88px}.famfamfam-flags.ws{width:16px;height:11px;background-position:-208px -99px}.famfamfam-flags.ye{width:16px;height:11px;background-position:-208px -110px}.famfamfam-flags.yt{width:16px;height:11px;background-position:-208px -121px}.famfamfam-flags.zw{width:16px;height:11px;background-position:-208px -132px}.famfamfam-flags.ch{width:11px;height:11px;background-position:-208px -143px}.famfamfam-flags.np{width:9px;height:11px;background-position:-208px -154px}
diff --git a/src/css/flags/famfamfam-flags.png b/src/css/flags/famfamfam-flags.png
new file mode 100644
index 0000000..c820e3b
Binary files /dev/null and b/src/css/flags/famfamfam-flags.png differ
diff --git a/src/css/loader.css b/src/css/loader.css
new file mode 100644
index 0000000..2477c18
--- /dev/null
+++ b/src/css/loader.css
@@ -0,0 +1,94 @@
+/*!
+ * # Semantic UI 2.3.3 - Loader
+ * http://github.com/semantic-org/semantic-ui/
+ *
+ * Released under the MIT license
+ * http://opensource.org/licenses/MIT
+ */
+
+/* Standard Size */
+.loader {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin: 0;
+ text-align: center;
+ z-index: 1000;
+ transform: translateX(-50%) translateY(-50%);
+
+ width: 2.28571429rem;
+ height: 2.28571429rem;
+ font-size: 1em;
+}
+
+/* Static Shape */
+.loader:before {
+ position: absolute;
+ content: '';
+ top: 0;
+ left: 50%;
+ width: 100%;
+ height: 100%;
+ border-radius: 500rem;
+ border: 0.2em solid rgba(0, 0, 0, 0.1);
+}
+
+/* Active Shape */
+.loader:after {
+ position: absolute;
+ content: '';
+ top: 0;
+ left: 50%;
+ width: 100%;
+ height: 100%;
+ animation: loader 0.6s linear;
+ animation-iteration-count: infinite;
+ border-radius: 500rem;
+ border: 0.2em solid transparent;
+ border-top-color: #767676;
+ box-shadow: 0 0 0 1px transparent;
+}
+
+.loader:before,
+.loader:after {
+ width: 2.28571429rem;
+ height: 2.28571429rem;
+ margin: 0 0 0 -1.14285714rem;
+}
+
+/* Active Animation */
+@keyframes loader {
+ from {
+ transform: rotate(0deg);
+ }
+
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+/* States */
+
+.loader.indeterminate:after {
+ animation-direction: reverse;
+ animation-duration: 1.2s;
+}
+
+.loader.disabled,
+.loader.hidden {
+ display: none;
+}
+
+/* Inverted */
+
+.loader.inverted {
+ color: rgba(255, 255, 255, 0.9);
+}
+
+.loader.inverted:before {
+ border-color: rgba(255, 255, 255, 0.15);
+}
+
+.loader.inverted:after {
+ border-top-color: #FFFFFF;
+}
diff --git a/src/css/style.css b/src/css/style.css
new file mode 100644
index 0000000..bef501a
--- /dev/null
+++ b/src/css/style.css
@@ -0,0 +1,400 @@
+/*!
+ * This file is a part of ts-website 2
+ * https://github.com/Wruczek/ts-website
+ * (c) Wruczek 2017 - 2019
+ */
+
+body {
+ position: relative;
+ padding-top: 90px;
+ padding-bottom: 6rem;
+ min-height: 100vh;
+ font-size: 15px;
+}
+
+.connectionproblems {
+ margin-top: 1rem;
+}
+
+.fa, .fas, .fab, .far, .fal {
+ margin-right: 0.5em
+}
+
+.language-switcher .dropdown-item {
+ cursor: pointer;
+}
+
+.card {
+ margin-bottom: 1rem;
+}
+
+.accordion .card {
+ margin-bottom: 0;
+}
+
+.accordion .card .card-header {
+ padding: .5rem !important;
+}
+
+.card .card-header * {
+ margin-bottom: 0;
+}
+
+.bottom-error-alert {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ margin: 0;
+ border-radius: 0;
+ text-align: center;
+ z-index: 998;
+}
+
+.card-titleblock {
+ margin-bottom: 1.5rem !important;
+}
+
+.card-titleblock .card-header {
+ text-align: center;
+ border: 0;
+ font-size: 1.2rem;
+}
+
+.footer {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ left: 0;
+
+ background-color: #f8f9fa;
+ padding: 0.8rem;
+ font-size: 1rem;
+ line-height: 2em;
+}
+
+.footer .footer-copyright {
+ font-size: 0.75rem;
+}
+
+/* Fixes https://github.com/twbs/bootstrap/issues/23374 */
+@media (max-width: 991px) {
+ .nav-fix-scroll {
+ overflow: auto;
+ max-height: 85vh;
+ align-items: unset;
+ }
+}
+
+/* Reimplement the btn-xs that was removed in Bootstrap 4 */
+/* https://github.com/twbs/bootstrap/issues/21881#issuecomment-341972830 */
+.btn-group-xs > .btn, .btn-xs {
+ padding : .25rem .4rem;
+ font-size : .875rem;
+ line-height : .5;
+ border-radius : .2rem;
+}
+
+/* ACCORDION */
+
+.accordion .card .card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.accordion .card .card-header .btn-link {
+ text-decoration: none;
+ text-align: inherit;
+ white-space: normal;
+}
+
+.accordion .card .card-header .copy-faq-url {
+ transition: opacity ease 250ms;
+ margin: 0 0.75rem 0 0;
+ cursor: pointer;
+}
+
+.accordion .card:not(:hover) .card-header .copy-faq-url {
+ opacity: 0;
+}
+
+/* Page/element specific */
+
+.badge.error-badge {
+ white-space: normal;
+ font-size: 1em;
+ font-weight: normal;
+}
+
+/* Server status */
+
+.server-status.loaded .status-loader {
+ display: none;
+}
+
+.server-status p {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ margin-bottom: 0.1rem;
+}
+
+.server-status .data span:first-child {
+ white-space: nowrap;
+}
+
+.server-status .data span:last-child {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+#loginModal .select-account .list-group .list-group-item {
+ cursor: pointer;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.login-button {
+ max-width: 150px;
+}
+
+#loginModal-codeconfirm .invalid-feedback {
+ margin-top: 0.5rem;
+ font-size: 100%;
+}
+
+/* Bans page */
+
+.ban-alert {
+ margin-bottom: 2rem;
+}
+
+.ban-alert.banned {
+ display: flex;
+ align-items: center;
+}
+
+/* Responsive datatables styles */
+
+table.dataTable>tbody>tr.child ul.dtr-details>li:first-child {
+ padding-top: 0;
+}
+
+table.dataTable > tbody > tr.child span.dtr-title {
+ display: inline-block;
+ min-width: 75px;
+ font-weight: bold;
+}
+
+table.dataTable>tbody>tr.child ul.dtr-details {
+ display: inline-block;
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+table.dataTable>tbody>tr.child ul.dtr-details>li {
+ padding: 0.5em 0;
+}
+
+table.dataTable > tbody > tr.parent td {
+ background-color: #282840
+}
+
+table.dataTable > tbody > tr.child td.child {
+ background-color: #2d2d4b
+}
+
+.dataTables_info {
+ white-space: normal !important
+}
+
+/* Viewer */
+
+.viewer-container {
+ font-size: 14px;
+}
+
+.viewer-container .channel-container:not(.is-server), .viewer-container .client-container {
+ margin-left: 1.4em;
+}
+
+.viewer-container .channel-container:not(.is-spacer) .channel, .viewer-container .client-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.viewer-container .channel-container:not(.is-spacer) > .channel > .channel-name,
+.viewer-container .channel-container:not(.is-spacer) > .channel > .channel-icons,
+.viewer-container .client-name, .viewer-container .client-icons {
+ display: flex;
+ align-items: center;
+}
+
+.viewer-container .channel-container:not(.is-spacer) > .channel > .channel-name,
+.viewer-container .client-name {
+ word-break: break-all; /* For all browsers */
+ word-break: break-word; /* For some browsers that support it - unofficial! */
+}
+
+.viewer-container .client-icons {
+ flex-wrap: wrap;
+ justify-content: flex-end;
+}
+
+.viewer-container .client-icons .icon,
+.viewer-container .client-icons .icon-flag,
+.viewer-container .channel-icons .icon {
+ margin-left: 0.5em;
+}
+
+.viewer-container .channel-container:not(.is-spacer) .channel,
+.viewer-container .client-container {
+ position: relative;
+ z-index: 0;
+ cursor: pointer;
+}
+
+.viewer-container .channel-container:not(.is-spacer) .channel::after,
+.viewer-container .client-container::after {
+ content: "";
+ z-index: -1;
+
+ position: absolute;
+ top: -3px;
+ left: -10px;
+ bottom: -3px;
+ right: -10px;
+
+ border-radius: 4px;
+ background-color: rgba(0, 0, 0, .15);
+ opacity: 0;
+ transition: opacity ease 300ms;
+}
+
+.viewer-container .channel-container:not(.is-spacer) .channel:hover::after,
+.viewer-container .client-container:hover::after,
+.viewer-container .channel-container:not(.is-spacer) .channel:focus::after,
+.viewer-container .client-container:focus::after {
+ opacity: 1;
+}
+
+.viewer-container .channel-name .icon, .viewer-container .client-name .icon {
+ margin-right: 0.5em;
+}
+
+.viewer-container .icon {
+ height: 16px;
+ max-width: 16px;
+}
+
+.viewer-container .channel-container.spacer-left > .channel {
+ text-align: left;
+}
+
+.viewer-container .channel-container.spacer-center > .channel {
+ text-align: center;
+}
+
+.viewer-container .channel-container.spacer-right > .channel {
+ text-align: right;
+}
+
+.viewer-container .channel-container.spacer-repeat > .channel {
+ overflow: hidden;
+ white-space: nowrap;
+}
+
+/* Admin status sidebar */
+
+.admin-status.admin-status-grouped .group-name {
+ /* Center icon with text (vertical & horizontal) */
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ font-family: var(--font-family-main);
+ font-size: 1.3em;
+}
+
+.admin-status.admin-status-grouped .group-name {
+ margin: 1em 0 0.1em 0;
+}
+
+.admin-status.admin-status-grouped .empty-group {
+ text-align: center;
+ font-style: italic;
+}
+
+/* No top spacing on the first group */
+/* Thats why I've put that extra DIV that wraps all groups */
+.admin-status.admin-status-grouped div:first-child .group-name {
+ margin-top: 0;
+}
+
+.admin-status.admin-status-grouped .group-name img,
+.admin-status.admin-status-list .nickname img {
+ height: 16px;
+ max-width: 16px;
+ margin-right: 0.25em;
+}
+
+.admin-status.admin-status-list .group-separator {
+ margin: 1.25em 0;
+}
+
+.admin-status .status-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 0.1em;
+}
+
+.admin-status .status-container .nickname {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+/* Group assigner */
+
+.group-assigner .list-group-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.group-assigner .list-group-item > div {
+ display: flex;
+ align-items: center;
+}
+
+/* The "icon-margin" is used when there is no icon, */
+/* its used to align it with other groups */
+.group-assigner .assigner-icon, .group-assigner .assigner-icon-margin {
+ width: 16px;
+ max-height: 16px;
+ margin-right: 0.3em;
+}
+
+.group-assigner .list-group-item:not(.assigner-header) {
+ cursor: pointer;
+}
+
+.group-assigner .assigner-category {
+ margin-bottom: 1.5rem;
+}
+
+.group-assigner .assigner-save {
+ width: 200px;
+ max-width: 100%;
+}
+
+.group-assigner .assigner-header .badge.badge-invalid {
+ background-color: red !important
+}
diff --git a/src/css/themes/dark.css b/src/css/themes/dark.css
new file mode 100644
index 0000000..dda0e7c
--- /dev/null
+++ b/src/css/themes/dark.css
@@ -0,0 +1,647 @@
+/*!
+ * This file is a part of ts-website 2
+ * https://github.com/Wruczek/ts-website
+ * (c) Wruczek 2017 - 2019
+ */
+
+@import url('https://fonts.googleapis.com/css?family=Exo+2');
+
+:root {
+ --site-background: #1e202f;
+ --site-secondary-color: #a61f67;
+ --site-accent-color: #f92552;
+ --site-text: #9e9caa;
+ --site-scrollbar-color: #1c88cc;
+
+ --font-family-sans-serif: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
+ --font-family-main: "Exo 2", "Roboto", sans-serif;
+}
+
+body {
+ background-color: var(--site-background);
+ color: var(--site-text);
+ font-family: var(--font-family-main);
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #fff;
+}
+
+.font-reading {
+ font-family: var(--font-family-sans-serif);
+}
+
+p, tbody {
+ font-family: var(--font-family-sans-serif);
+}
+
+.btn, thead, .dataTables_wrapper {
+ font-family: var(--font-family-main);
+}
+
+a {
+ color: #fff;
+ transition: color 0.3s ease;
+}
+
+a:hover {
+ color: var(--site-secondary-color);
+ text-decoration: none;
+}
+
+::selection {
+ background-color: var(--site-secondary-color);
+}
+
+
+/* ============ */
+/* NAVBAR STUFF */
+/* ============ */
+
+#main-navbar {
+ background-color: #323150 !important;
+ border-bottom: 1px solid #3c3b5b;
+}
+
+#main-navbar .nav-item {
+ padding: 0.5rem 0;
+ transition: background-color 0.5s ease;
+}
+
+#main-navbar .navbar-nav .nav-link {
+ color: rgba(255, 255, 255, 0.8);
+ text-transform: uppercase;
+}
+
+#main-navbar .nav-item.active,
+#main-navbar .nav-item:hover,
+#main-navbar .nav-item.dropdown.show {
+ background-color: #282840;
+}
+
+#main-navbar .nav-item.active .nav-link,
+#main-navbar .nav-item:hover .nav-link,
+#main-navbar .nav-item.dropdown.show .nav-link {
+ color: #fff;
+}
+
+@media (max-width: 991px) {
+ #main-navbar .navbar-collapse {
+ margin-left: -1rem;
+ margin-right: -1rem;
+ }
+
+ #main-navbar .navbar-nav .nav-link {
+ padding-left: 1rem;
+ padding-right: 1rem;
+ color: rgba(255, 255, 255, 0.65);
+ }
+}
+
+@media (min-width: 992px) {
+ /* Remove padding from navbar and add it later to navbar items */
+ #main-navbar {
+ padding: 0;
+ }
+
+ #main-navbar .navbar-nav {
+ border-left: 1px solid #3c3b5b;
+ }
+
+ #main-navbar .navbar-nav li {
+ border-right: 1px solid #3c3b5b;
+ }
+
+ /* Add bigger padding between navbar items */
+ #main-navbar .navbar-nav .nav-link {
+ padding-right: .9rem;
+ padding-left: .9rem;
+ }
+
+ /* ================================ */
+ /* Navbar underline hover effect */
+ /* Taken from http://bit.ly/2xkPi0k */
+ /* ================================ */
+ #main-navbar .nav-item {
+ position: relative;
+ }
+
+ #main-navbar .nav-item:after {
+ content: "";
+ position: absolute;
+ top: calc(100% - 0.1rem);
+ border-bottom: 0.125rem solid var(--site-accent-color);
+ left: 50%;
+ right: 50%;
+ transition: left 0.5s ease, right 0.5s ease;
+ }
+
+ #main-navbar .nav-item:hover::after,
+ #main-navbar .nav-item.active::after,
+ #main-navbar .nav-item.show::after {
+ left: 0;
+ right: 0;
+ }
+
+ /* =============================== */
+ /* Hover effect for dropdown items */
+ /* =============================== */
+ .dropdown-item {
+ border-left: 0 solid var(--site-accent-color);
+ transition: border-left-width 0.1s ease, padding-left 0.1s ease, background-color 0.5s ease;
+ }
+
+ .dropdown-item:hover,
+ .dropdown-item.active {
+ border-left-width: 2px;
+ padding-left: calc(1.5rem - 2px);
+ }
+}
+
+/* ========= */
+/* DROPDOWNS */
+/* ========= */
+
+.dropdown-menu {
+ background-color: #323150;
+ color: inherit;
+}
+
+.dropdown-item {
+ color: rgba(255, 255, 255, 0.8);
+}
+
+.dropdown-item.active,
+.dropdown-item:focus,
+.dropdown-item:hover {
+ color: #fff;
+ background-color: #282840;
+}
+
+/* ======= */
+/* BUTTONS */
+/* ======= */
+
+.btn-primary, .btn-primary.disabled, .btn-primary:disabled {
+ background-color: var(--site-secondary-color);
+ border-color: var(--site-secondary-color);
+}
+
+.btn-primary:hover {
+ background-color: #861953;
+ border-color: #861953;
+}
+
+.btn-primary:not(:disabled):not(.disabled).active,
+.btn-primary:not(:disabled):not(.disabled):active,
+.show > .btn-primary.dropdown-toggle {
+ background-color: #69182d;
+ border-color: #69182d;
+}
+
+.btn-primary.focus, .btn-primary:focus,
+.btn-primary:not(:disabled):not(.disabled).active:focus,
+.btn-primary:not(:disabled):not(.disabled):active:focus,
+.show > .btn-primary.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(166, 31, 103, 0.5); /* secondary color with 50% opacity */
+}
+
+/* ====== */
+/* INPUTS */
+/* ====== */
+
+.form-control, .custom-select {
+ color: #fff;
+ background-color: #282840;
+ border-color: #282840;
+}
+
+.form-control:focus, .custom-select:focus {
+ color: #fff;
+ background-color: #282840;
+
+ border-color: var(--site-secondary-color);
+ box-shadow: 0 0 0 0.2rem rgba(166, 31, 103, 0.30); /* secondary color with 30% opacity */
+}
+
+.form-control::-webkit-input-placeholder {
+ color: var(--site-text);
+}
+
+.form-control::-moz-placeholder {
+ color: var(--site-text);
+}
+
+.form-control:-ms-input-placeholder {
+ color: var(--site-text);
+}
+
+.form-control::-ms-input-placeholder {
+ color: var(--site-text);
+}
+
+.form-control::placeholder {
+ color: var(--site-text);
+}
+
+.form-control[disabled],
+.input-text[disabled],
+select[disabled],
+.form-control[readonly],
+.input-text[readonly],
+select[readonly],
+fieldset[disabled] .form-control,
+fieldset[disabled] .input-text,
+fieldset[disabled] select,
+.custom-select[disabled] {
+ background-color: #212135;
+ border-color: transparent;
+}
+
+.form-control-plaintext {
+ color: var(--site-text);
+}
+
+.input-group-text {
+ color: var(--site-text);
+ background-color: #212135;
+ border: none;
+}
+
+.custom-control-label::before,
+.custom-control-input:disabled~.custom-control-label::before {
+ background-color: #212135;
+}
+
+.custom-control-input:checked~.custom-control-label::before {
+ background-color: var(--site-secondary-color) !important;
+}
+
+/* Lighter on a list group item */
+
+.list-group-item .custom-control-label::before,
+.list-group-item .custom-control-input:disabled~.custom-control-label::before {
+ background-color: #323150;
+}
+
+/* ======================================= */
+/* ALERTS */
+/* taken from Bootswatch Darkly */
+/* Bootswatch is (c) 2012-2018 Thomas Park */
+/* ======================================= */
+
+.alert {
+ border: none;
+ color: #fff;
+}
+
+.alert a,
+.alert .alert-link {
+ color: #fff;
+ text-decoration: underline;
+}
+
+.alert-primary {
+ background-color: #375a7f;
+}
+
+.alert-secondary {
+ background-color: #444;
+}
+
+.alert-success {
+ background-color: #00bc8c;
+}
+
+.alert-info {
+ background-color: #3498DB;
+}
+
+.alert-warning {
+ background-color: #F39C12;
+}
+
+.alert-danger {
+ background-color: #E74C3C;
+}
+
+.alert-light {
+ background-color: #303030;
+}
+
+.alert-dark {
+ background-color: #adb5bd;
+}
+
+.alert-dismissible .close {
+ padding: 0.5rem 1rem;
+}
+
+.alert code {
+ background-color: var(--site-background);
+ padding: 0.15em;
+}
+
+/* ========== */
+/* PAGINATION */
+/* ========== */
+
+.page-link {
+ color: var(--site-text);
+ background-color: #282840;
+ border-color: #3c3b5b;
+}
+
+.page-link:hover {
+ color: var(--site-text);
+ background-color: #212135;
+ border-color: #212135;
+}
+
+.page-link.light-hover:hover {
+ color: var(--site-text);
+ background-color: #323150;
+ border-color: #323150;
+}
+
+.page-link:focus {
+ box-shadow: 0 0 0 0.2rem rgba(166, 31, 103, 0.30); /* secondary color with 30% opacity */
+}
+
+.page-item.active .page-link {
+ color: #fff;
+ background-color: var(--site-secondary-color);
+ border-color: var(--site-secondary-color);
+}
+
+.page-item.disabled .page-link {
+ color: #5d666e;
+ background-color: #212135;
+ border-color: #212135;
+}
+
+/* ===== */
+/* CARDS */
+/* ===== */
+
+.card {
+ background-color: transparent;
+ border-color: transparent;
+}
+
+.card {
+ border: 1px solid #3c3b5b;
+ background-color: #323150;
+}
+
+.card .card-body {
+ font-family: var(--font-family-sans-serif);
+ padding: 1rem;
+}
+
+.card.card-accent > .card-header {
+ position: relative;
+ overflow: hidden;
+ color: #fff;
+}
+
+.card.card-accent > .card-header::before {
+ content: "";
+ display: block;
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ height: 2px;
+ background-color: var(--site-accent-color);
+}
+
+.card.card-titleblock {
+ text-transform: uppercase;
+}
+
+.card .card-header {
+ padding-left: 1rem;
+ padding-right: 1rem;
+ background-color: rgba(0, 0, 0, .15);
+}
+
+.card .card-header.bigger-title {
+ font-size: 1.15rem
+}
+
+.card .card-header a {
+ text-decoration: none !important;
+}
+
+.card .card-body p:last-child {
+ margin-bottom: 0;
+}
+
+/* ===== */
+/* MODAL */
+/* ===== */
+
+.modal .modal-content {
+ border: 1px solid #3c3b5b;
+ background-color: #323150;
+}
+
+.modal .modal-header {
+ background-color: rgba(0, 0, 0, .15);
+ border-bottom: 1px solid rgba(0, 0, 0, .125);
+}
+
+.modal .modal-body {
+ font-family: var(--font-family-sans-serif);
+}
+
+.modal .modal-header .close {
+ color: #fff !important;
+ font-family: var(--font-family-sans-serif);
+}
+
+/* ========== */
+/* LIST-GROUP */
+/* ========== */
+
+.list-group-item {
+ color: #fff;
+ background-color: #282840;
+}
+
+.list-group-item-action:focus,
+.list-group-item-action:hover,
+.list-group-item-action:active {
+ color: #fff;
+ background-color: #232338;
+}
+
+/* ========= */
+/* ACCORDION */
+/* ========= */
+
+.accordion .card .card-header {
+ font-family: var(--font-family-main);
+}
+
+.accordion .card .card-header .btn-link {
+ color: #fff;
+}
+
+/* ====== */
+/* TABLES */
+/* ====== */
+
+.table {
+ font-size: 0.85em;
+}
+
+.table thead th {
+ border-bottom: none;
+ color: #fff;
+ text-transform: uppercase;
+ white-space: nowrap;
+}
+
+.table td, .table th {
+ border-top-color: #494770;
+ padding: .65rem;
+}
+
+/* ============= */
+/* PROGRESS BARS */
+/* ============= */
+
+.progress {
+ background-color: #2c2e3e;
+}
+
+/* ======== */
+/* POPOVERS */
+/* ======== */
+
+/*
+.popover {bgcolor, border}
+ .popover-header {bgcolor, border}
+ .popover-body {color}
+*/
+
+.popover {
+ border: 1px solid #3c3b5b;
+ background-color: #323150;
+}
+
+.popover-header {
+ background-color: rgba(0, 0, 0, .15);
+ border-bottom: 1px solid #3c3b5b;
+ color: #fff;
+ font-family: var(--font-family-main);
+}
+
+.popover-body {
+ color: rgba(255, 255, 255, 0.8)
+}
+
+/* ====== */
+/* FOOTER */
+/* ====== */
+
+.footer {
+ background-color: #282840;
+}
+
+/* =============== */
+/* INVERTED LOADER */
+/* =============== */
+
+.loader {
+ color: rgba(255, 255, 255, 0.9);
+}
+
+.loader:before {
+ border-color: rgba(255, 255, 255, 0.15);
+}
+
+.loader:after {
+ border-top-color: #FFFFFF;
+}
+
+/* ========= */
+/* SCROLLBAR */
+/* ========= */
+
+::-webkit-scrollbar {
+ width: 5px;
+ height: 5px;
+ background-color: var(--site-background);
+}
+
+::-webkit-scrollbar-thumb {
+ border-radius: 3px;
+ background: var(--site-accent-color)
+}
+
+::-webkit-scrollbar-thumb:window-inactive {
+ background: var(--site-accent-color)
+}
+
+::-webkit-scrollbar-track-piece {
+ display: none
+}
+
+/* ============ */
+/* ADMIN STATUS */
+/* ============ */
+
+.admin-status .status-container .status .badge-success {
+ background-color: var(--site-secondary-color);
+}
+
+.admin-status .status-container .status .badge-secondary {
+ background-color: var(--site-background);
+}
+
+.admin-status .status-container .status .badge-secondary {
+ background-color: var(--site-background);
+}
+
+/* ============== */
+/* GROUP ASSIGNER */
+/* ============== */
+
+.group-assigner .assigner-header {
+ font-size: 1.1em;
+ background-color: #212135;
+ font-family: var(--font-family-main);
+}
+
+.group-assigner .assigner-header .badge.badge-primary {
+ background-color: var(--site-secondary-color);
+}
+
+.group-assigner .assigner-header .badge.badge-invalid {
+ background-color: red !important
+}
+
+
+/* ============= */
+/* PAGE-SPECIFIC */
+/* ============= */
+
+a[data-connectionproblem] {
+ color: #000;
+}
+
+/* Server Status */
+
+.server-status .data .badge {
+ color: #fff;
+ background-color: var(--site-secondary-color);
+}
+
+/* Login */
+
+#loginModal .not-connected .waiting-connect {
+ color: #fff;
+}
diff --git a/src/faq.php b/src/faq.php
new file mode 100644
index 0000000..86f12a8
--- /dev/null
+++ b/src/faq.php
@@ -0,0 +1,16 @@
+getDb();
+$qa = $db->select("faq", "*");
+
+$data = [
+ "additionaltext" => 'composer update
in the ' .
+ '' . realpath(__BASE_DIR) . '
directory'
+ );
+}
+
+ini_set("display_errors", 1);
+ini_set("display_startup_errors", 1);
+error_reporting(E_ALL);
+set_time_limit(0);
+
+$stepNumber = empty($_GET["step"]) || !file_exists(__DIR__ . "/pages/" . (int)$_GET["step"] . ".php") ? 1 : (int) $_GET["step"];
+?>
+
+
+
+
+
+
+ This wizard will guide you through the installation process of TS-website.
+Please enable Javascript before continuing!
++ If you encounter any problems please make sure you check the + wiki. +
+Go to the next step whenever you are ready!
+ + +utf8_encode
exists",
+ $result ? 1 : 0,
+ $result ?
+ "Function not found, using polyfill" :
+ "Function exists"
+ );
+ }
+
+ // password_hash and password_verify
+ {
+ $result = PHP_VERSION_ID >= 50500 && password_verify(
+ "ayy-lmao-m88", password_hash("ayy-lmao-m88", PASSWORD_DEFAULT)
+ );
+
+ showCheckResult(
+ "password_hash & password_verify",
+ $result ? 0 : 2,
+ $result ?
+ "Functions exists and work" :
+ "Please make sure your PHP version supports BCRYPT and BLOWFISH"
+ );
+ }
+
+ displayCategory("Extension checks");
+
+ // Extensions check
+ {
+ foreach (["mbstring", "json", "pdo_mysql", "tokenizer", "curl"] as $extension) {
+ $result = extension_loaded($extension);
+
+ showCheckResult(
+ "$extension
extension",
+ $result ? 0 : 2,
+ $result ?
+ "Extension installed and loaded" :
+ 'Please install or enable ' . $extension . '
extension'
+ );
+ }
+ }
+
+ displayCategory("File / directory permission checks");
+
+ // file / directory writable checks
+ {
+ // path => true if file, false if directory
+ $paths = [
+ __CONFIG_FILE => true,
+ __INSTALLER_LOCK_FILE => true,
+ __CACHE_DIR => false,
+ __CACHE_DIR . "/templates" => false,
+ __CACHE_DIR . "/servericons" => false,
+ ];
+
+ foreach ($paths as $path => $isFile) {
+ $exists = file_exists($path);
+
+ // If file / directory doesnt exists try to create it and update the variable
+ if(!$exists)
+ $exists = $isFile ? @touch($path) : @mkdir($path);
+
+ $writable = is_writable($path);
+ $basename = basename($path);
+
+ // we are using a custom method instead of realpath,
+ // because it does not work with non-existing files
+ $realpath = resolveFilename($path);
+
+ $msg = "Yes";
+
+ if(!$writable)
+ $msg = "Please make $realpath
writable";
+
+ if(!$exists)
+ $msg = ($isFile ? "File" : "Directory") . " $realpath
does not exists, please create it";
+
+ showCheckResult("Is $basename
writable?", $exists && $writable ? 0 : 2, $msg);
+ }
+ }
+
+ displayCategory("Miscellaneous");
+
+ // cache test
+ {
+ $result = false;
+
+ try {
+ require_once __PRIVATE_DIR . "/vendor/autoload.php";
+ $cache = new Wruczek\PhpFileCache\PhpFileCache();
+ $teststring = "cachetest123";
+ $cache->store("installertest", $teststring, 3);
+ $result = $cache->retrieve("installertest") === $teststring;
+ $cache->clearCache();
+ } catch (Exception $e) {}
+
+ showCheckResult(
+ "Cache save and read test",
+ $result ? 0 : 2,
+ $result ?
+ "Save and read success" :
+ "Something went wrong! Please make sure that private/cache
directory is writable"
+ );
+ }
+
+ // template test
+ {
+ if($result) {
+ if(extension_loaded("mbstring")) {
+ $result = false;
+
+ try {
+ $latte = new Latte\Engine();
+ $latte->setTempDirectory(__CACHE_DIR);
+ $latte->setLoader(new Latte\Loaders\StringLoader());
+
+ $render = @$latte->renderToString('Hello, {$test|upper}!', array("test" => "Wruczek"));
+
+ $result = $render === "Hello, WRUCZEK!";
+ } catch (Exception $e) {}
+
+ showCheckResult(
+ "Template render and cache test",
+ $result ? 0 : 2,
+ $result ?
+ "Render and cache success" :
+ "Something went wrong! Please make sure that private/cache
directory is writable"
+ );
+ } else {
+ showCheckResult("Template render and cache test", 2, "mbstring
extension not found, cannot start the test");
+ }
+ } else {
+ showCheckResult("Template render and cache test", 2, "private/cache
directory is not writable, cannot start the test");
+ }
+ }
+
+}
+
+// Utils
+
+function showCheckResult($name, $state, $resulttext) {
+ if($state === 0) {
+ $attr = "fa-check-circle color-success";
+ } else if($state === 1) {
+ $attr = "fa-minus-circle color-warning";
+ } else {
+ $attr = "fa-times-circle color-danger";
+
+ if(!defined("CANNOT_INSTALL"))
+ define("CANNOT_INSTALL", true);
+ }
+
+ ?>
+ " . __CONFIG_FILE . "
! Please check the file/directory permissions";
+ } else {
+ header("Location: ?step=" . ($stepNumber + 1));
+ }
+ }
+ } catch (Exception $e) {
+ $errormessage = htmlspecialchars("Error " . $e->getCode() . ": " . $e->getMessage());
+
+ if($e->getCode() === 1045) {
+ $errormessage .= '
+ If you wish, you can remove the installer
directory.
+
' + description + ' | ' + body += '' + value + ' | ' + body += '
{_"BANS_BANNED_ALERT_TITLE", $ipbanned["invoker"]}
+ {if $ipbanned["reason"]} + {_"BANS_BANNED_ALERT_REASON", $ipbanned["reason"]} + {/if} +{_"BANS_HEADER_NAME"} | +{_"BANS_HEADER_REASON"} | +{_"BANS_HEADER_INVOKER"} | +{_"BANS_HEADER_BANDATE"} | +{_"BANS_HEADER_EXPIRES"} | +
---|---|---|---|---|
{$ban["name"]} | +{$ban["reason"]} | +{$ban["invoker"]} | +{$ban["created"]|fullDate} | +{$ban["duration"] ? ($expiretime|fuzzyDateAbbr) : ("BANS_NEVEREXPIRES"|translate)} | +
+ + + + + + + +
+ ++ + + + + + + +
+ ++ + + + + + +
+ ++ +
+ +Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.
+Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula.
+This line of text is meant to be treated as fine print.
+The following is rendered as bold text.
+The following is rendered as italicized text.
+An abbreviation of the word attribute is attr.
+Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.
+Nullam id dolor id nibh ultricies vehicula ut id elit.
+Etiam porta sem malesuada magna mollis euismod.
+Donec ullamcorper nulla non metus auctor fringilla.
+Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
+Maecenas sed diam eget risus varius blandit sit amet non magna.
+++Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
+ +
++Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
+ +
++Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
+ +
Type | +Column heading | +Column heading | +Column heading | +
---|---|---|---|
Active | +Column content | +Column content | +Column content | +
Default | +Column content | +Column content | +Column content | +
Primary | +Column content | +Column content | +Column content | +
Secondary | +Column content | +Column content | +Column content | +
Success | +Column content | +Column content | +Column content | +
Danger | +Column content | +Column content | +Column content | +
Warning | +Column content | +Column content | +Column content | +
Info | +Column content | +Column content | +Column content | +
Light | +Column content | +Column content | +Column content | +
Dark | +Column content | +Column content | +Column content | +
Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.
+Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit.
+Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork.
+Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater.
+Best check yo self, you're not looking too good. Nulla vitae elit libero, a pharetra augue. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
+This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.
+It uses utility classes for typography and spacing to space content out within the larger container.
++ Learn more +
+Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.
+ Donec id elit non mi porta. + + +Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.
+ Donec id elit non mi porta. + +Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+Some quick example text to build on the card title and make up the bulk of the card's content.
+ Card link + Another link +{$news["description"]|noescape}
+