Virtubrick

- Mostly rebranded the website to Virtubrick, following Icseon's decision to stop paying for gtoria.net.
- Name is dynamic and can be configured via the .env file.
- Admin user search page.
- Made a page explaining what the purpose of testing sites are.
- Readded maintenance page.
- Created a batch file for (re)generating the ssl certificate.
- Reworking admin configuration page.
- Indev Roblox asset auto uploader.
- Component for user headshot/name. Toggleable status visualization.
- Virtubrick-styled tables.
This commit is contained in:
Graphictoria 2022-12-27 22:47:22 -05:00
parent de46b30b8a
commit 056d12d309
133 changed files with 1427 additions and 979 deletions

BIN
etc/art/vbrick.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 977 KiB

BIN
etc/art/virtubrick.blend Normal file

Binary file not shown.

View File

@ -1,20 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDRzCCAi+gAwIBAgIURJTrNof9lM8yv+OAHaWFPOgomlMwDQYJKoZIhvcNAQEL
BQAwMzELMAkGA1UEBhMCVVMxJDAiBgNVBAMMG0dyYXBoaWN0b3JpYS1EZXZlbG9w
bWVudC1DQTAeFw0yMjA0MTUwMjMzMzNaFw0yNTAyMDIwMjMzMzNaMDMxCzAJBgNV
BAYTAlVTMSQwIgYDVQQDDBtHcmFwaGljdG9yaWEtRGV2ZWxvcG1lbnQtQ0EwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjARnva6VgZ5jGWsHSMgR03GTv
rKXq0YGIkfsliFFkVMXpH7B2orU5Zt9I23vJ7NX5bsm8977NWCqt80lC0wt4Ld58
0JYjFkM/qgzDip6dUDTcQWdS81kq4zg0yMIiMaEddGBRmhJOsngX3iDNAypZ3XJQ
qZZ+ENTtDIh9+pqrt4+QFDMKTLNrcANdFlxfkriVhwQX/JmktGKIxCyG+4hSvuw4
pCvsVPso0+7lGr9GNIzEXBD2Jvwtr2buXYg4yg0wx92PMeaSLU0OKKS7BfEPdikm
rKanuNzXNcAPQHplLeXzfgO1m6Hi3thNIaDmrqGcnQ6vfKv2j6LaZaWp649lAgMB
AAGjUzBRMB0GA1UdDgQWBBTH+uxCWs1TcDYNFptpXWMESc+MejAfBgNVHSMEGDAW
gBTH+uxCWs1TcDYNFptpXWMESc+MejAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
DQEBCwUAA4IBAQB6nHMSv+3rfO50t/e4pc613nIYbDv9/PnPouFwt8AiYk5ifpIa
WUZmupwY6Yl2JynzSHFFpe1afimd039LblUetlfDbv2Z+H4IBJ8lgCZE8GIskKNN
wpWF9Ovog0995fubUQdG9QU0JeCrlLDVlaDYhz1ImjP3KdOSZHZRWDdrzicwH6nQ
GZe0CgSML4S/YMPX/1BiEawpugcnAbDW3ZPh0md9FlsNt/rdL1PZiv0y9PM9cd8k
mqfVgPD7OAwihrjGVzFtmKzis0PbNpaydmpzII1j8OaHc8lLMSpIuGykbrfocD3O
p7zJ6bVvpr9PohKjIbslj2gkrMb7gq9EH4Tv
MIIDNzCCAh+gAwIBAgIUeRbZ6wwayGbn2Ava8XTPh6reXu0wDQYJKoZIhvcNAQEL
BQAwKzELMAkGA1UEBhMCVVMxHDAaBgNVBAMME1ZpcnR1QnJpY2stTG9jYWwtQ0Ew
HhcNMjIxMjI0MDQwNzM1WhcNMjUxMDEzMDQwNzM1WjArMQswCQYDVQQGEwJVUzEc
MBoGA1UEAwwTVmlydHVCcmljay1Mb2NhbC1DQTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAJdBvaTyxCo7+nJV3pSMVKFXc4VOLhlg0BZrAytZR64lC2jg
0JOI1qwQKeBRFKVN+ZsmfEOyIg82Hbtu+7ZzbvX1wKdcU/m9FT8JgEZ0rT8koN4C
S2idiTbNSiNXKkicbSjw6CfZEEL+LZaziR+Qt1hh/PMC6U5haz0bUtm8cKV1tfv8
aGs/GXyoZ35cUJq6YNWlE0Bxyt7LvEH7C/H5c2TIrUOLp+zTcMlWTxelkeBp51x9
cgOP5fILPOgs7IZ2wi8yUjfGBSfVWt6VyDp7vaws7/HozWta/tiGiLRImbulJeAw
BhPesBz6VUnaDeovHiwIFuFJHugPqv4TKNdXoOMCAwEAAaNTMFEwHQYDVR0OBBYE
FLo8qb1zkIVtEwu1whODHUf4Lq5dMB8GA1UdIwQYMBaAFLo8qb1zkIVtEwu1whOD
HUf4Lq5dMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADqVAf8P
aZ2M8YmmJnCxyKNmH1eeWwvPQB8+3H15auPDPXblqN48lw+pbN1dciBFlvpRSCEU
Ykdodo2W+Jyy1h8/zCVT4Vjz6OuQvKQSs/7sbxnx7txZ+3UTf0JJELXhyYtn4Sx+
+z9IjULy2zy+8QgK7c/QliBCXkTgStg0NayNhqVNM9lKAphpYJM99cgdiW7Mun+R
hMFj/QORCMOKGNYsR3ktlYPzXb8qzGhgX94RAY8wYfRtqCXbOq+Mpi8BRNF2G/0n
n+Pay/7yfdhiTtORrSjewsjSTElS9QzXrk26PreWWJWTAYuPa6l09Vxd4r8bYcqa
Nk9CdC6FVWP6x/I=
-----END CERTIFICATE-----

View File

@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCjARnva6VgZ5jG
WsHSMgR03GTvrKXq0YGIkfsliFFkVMXpH7B2orU5Zt9I23vJ7NX5bsm8977NWCqt
80lC0wt4Ld580JYjFkM/qgzDip6dUDTcQWdS81kq4zg0yMIiMaEddGBRmhJOsngX
3iDNAypZ3XJQqZZ+ENTtDIh9+pqrt4+QFDMKTLNrcANdFlxfkriVhwQX/JmktGKI
xCyG+4hSvuw4pCvsVPso0+7lGr9GNIzEXBD2Jvwtr2buXYg4yg0wx92PMeaSLU0O
KKS7BfEPdikmrKanuNzXNcAPQHplLeXzfgO1m6Hi3thNIaDmrqGcnQ6vfKv2j6La
ZaWp649lAgMBAAECggEADgCbd31uBqbHkSx9L18EEnzXP957Hz2RjMeLhTkdUsrU
eHb0K/DEtBJh9mqCSwGJDQUHF/BJR+79tZUrUy35c4CvNtYdO5TfQIINWCPZhcZ8
z/nfVBka7Qv5SVGAmbrdLgBQANqFHZUHq3c1pp7Rvcf/2K2Ew74S6G0V8Yp8TGlU
RrRtM5ovdePPFTx//V5DhktofjSlPNOO4g4oaXdR9DOlD9iTp9/WbgfE17Qc4Vz7
4Xc5qXn/q6MSPkejkMzTtTGpfCRO4rWrs2fJwj8CEuHIKL1cJw88rv1i2MT95buR
XEficvcD5jwFXoDAnyaMwqKmBr3inlmTnqlHkr9OiQKBgQC4FDNYoUNvuq4ZKrDK
BYAR9tLaNKfiwIDYn1trB2obL9WaojmWDFJM89IZlWqDePPCyVw+eItLi0/ZBvDl
3UjTa7ET4BEwbdSYAVlJlI5viAnyu57tU3aMg1QvnP0wZh7nBRBRlk4rWBDUs7X9
vo8YXXVejDyJh6LQ5uM3FWIKvQKBgQDisP4blS8YSIh76YAPhX/HZEknO+q1cAQ2
/5wBTWDddt9NftUa7i/YA4vquu0ssc4babteXe3aPFJN8SkutjR6jmFArB/nMeIp
9+G1TGEBUtzhdnpOakLweOSJ7OBA1bD89c6CE2nA1VC+TyWJFSFqedpjcQwHdRD+
uyOn+hg1yQKBgADr2PXwmK3OeWCW3huku2dbnOKKsOxpmjt7ULHQb6+DJcaIWVFu
7lqEPeDy5n2R9WZcK6IEaG4QXG3xovMDkIG+YDyBOpTLd+zq1M+RdsUIIUSdu8Xk
TQuW/KzgVEQRvsXZOKOv5ORCpJLr81U5xu2QSi4W9Zaany38edakvMDhAoGAcn7s
yWevMren39YO7UgDQuU/IYbcxClAp7qww+OeMh1RKeYOopx9I8Ce0b75/eIMdMIR
dddBREHFXEKbB1HV7bSuICkPsAj87y+ZG6XpNO7ySxo5KhP3nVeiLpuqpHSKASnx
1LcTaecT8hstnTBEAXBsQl+dsMKLA+3nU3c49SkCgYApyJ8XCv1uZDInFimJo3Hq
MXLkhxkzj9PJBWqps9ps6/QjthHGFYT9WMdcF2iNSTxoS5p1/O7wofQ3EHDiNlaz
uhOKhYeA01l52vZmgm8bCInLa9fcAe0oGnfyQI7oyBHq0J3FoVTmpG92GC7e3/cc
pPVAfmA8k77J9R/XWJylkA==
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXQb2k8sQqO/py
Vd6UjFShV3OFTi4ZYNAWawMrWUeuJQto4NCTiNasECngURSlTfmbJnxDsiIPNh27
bvu2c2719cCnXFP5vRU/CYBGdK0/JKDeAktonYk2zUojVypInG0o8Ogn2RBC/i2W
s4kfkLdYYfzzAulOYWs9G1LZvHCldbX7/GhrPxl8qGd+XFCaumDVpRNAccrey7xB
+wvx+XNkyK1Di6fs03DJVk8XpZHgaedcfXIDj+XyCzzoLOyGdsIvMlI3xgUn1Vre
lcg6e72sLO/x6M1rWv7Yhoi0SJm7pSXgMAYT3rAc+lVJ2g3qLx4sCBbhSR7oD6r+
EyjXV6DjAgMBAAECggEAJTi80fwZ0Ojcm0lNUlHsO535JBtWldEws+uWppK8ZHri
QWddfIjmhwYdQAHD6l/zZj5EwyXxYrvm+ip4D/B9JFLbG3RJiAIDWfVdFzl8Lrc1
TRzUcMSfsRg4v9Sh56dy52nNP40Xhtzk3BqHSnjC3aGTbTvQrQSlLq7sJv/L2rNp
YmE3yyQ3evXEw2GHXbhd2kE1e6vI/C1U5h91NSYk2D8DvK54gB3xcOzHG6xfUger
i4gUjAFexEQoBMHcmSgYiaGvkbp7O9IjHyKQOsIOYw5i9fQPqs4IlzAi8HBB88BJ
WUEIwil06mz+IKKK/2weZkddB3ZmIwbHm8jkpzAUiQKBgQC7LD8U1xqKhmOU+TNW
UTDcTlLhz4bX8Jl09fqwGlbK19gJFFTAMuVWWx2au4ATJic+UGPLA6hs7q7kKsrU
tP17afZTNuFBFBzQPfDgzRZOfJWmRSE7PFbVA7nRNtIW8e549cIg9PhuDQjEdyr7
/1Zk6LqnKIYrMYo8aVe+Gu10mwKBgQDO4H4PUygQhtU2UITVcN43suqrlvJJuC6H
+WXfXlcf2YITHwtEGcyNvOETBbs85M0x+AzLJnJGNzqIE3F8FT4a2EduBi/G26he
CNW9st66u+yfnduuTDpvxDNICn71E7pbRQuI3FqyarW0s/lO63jDYkaEw8t1aJ2I
ouYwaFI1WQKBgFgFgtTmI5EpigMw/jeFjxjLrKaM1bkPaNtcIjxW5qIVx37dlM2e
IcPurYlqy9w1gRcI7yU13yr7RDwA88n8I4i6WCDiGiRktPgpaPIPAIKAjE/ZCru0
sJEUY3pD8aDgvWkdCeI90ebPMmRSNmCzv4lM+RpLMG13qq6mS6EXQLwpAoGAIPCH
weLotzDw0/QgImgVSeMYEHg5XdmQtx/Tw6wezThxyJ+hyJcfBdZ0M/YuqPR5Y6Ju
Tw5xFZMHo9EMucgcGmQjg3ZCtzQUa9yWQ90uL6dqdsPIzcjfaRphW/An5NfeTVgC
DSmg21W4VuxtHs7JbLrCJbOTOr+Mjcv6QOzrYgkCgYEAt6T0WimGNXumAdGyIi8j
zWC/Oa7tSYwLrgpnXYdtBKa4oxJDQr3L2zkTZ0K76J5dQuTM3q/IKbGmP9p8K9MB
Nx5U5BlFFpeUC1pPt7noJwmG4KcCt9GekPIhV0+44hLOvIEFznugc5/Y5XvqDFGq
ZSEy8mDXVww7JCsG4avq0Fk=
-----END PRIVATE KEY-----

View File

@ -1,20 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDRzCCAi+gAwIBAgIURJTrNof9lM8yv+OAHaWFPOgomlMwDQYJKoZIhvcNAQEL
BQAwMzELMAkGA1UEBhMCVVMxJDAiBgNVBAMMG0dyYXBoaWN0b3JpYS1EZXZlbG9w
bWVudC1DQTAeFw0yMjA0MTUwMjMzMzNaFw0yNTAyMDIwMjMzMzNaMDMxCzAJBgNV
BAYTAlVTMSQwIgYDVQQDDBtHcmFwaGljdG9yaWEtRGV2ZWxvcG1lbnQtQ0EwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjARnva6VgZ5jGWsHSMgR03GTv
rKXq0YGIkfsliFFkVMXpH7B2orU5Zt9I23vJ7NX5bsm8977NWCqt80lC0wt4Ld58
0JYjFkM/qgzDip6dUDTcQWdS81kq4zg0yMIiMaEddGBRmhJOsngX3iDNAypZ3XJQ
qZZ+ENTtDIh9+pqrt4+QFDMKTLNrcANdFlxfkriVhwQX/JmktGKIxCyG+4hSvuw4
pCvsVPso0+7lGr9GNIzEXBD2Jvwtr2buXYg4yg0wx92PMeaSLU0OKKS7BfEPdikm
rKanuNzXNcAPQHplLeXzfgO1m6Hi3thNIaDmrqGcnQ6vfKv2j6LaZaWp649lAgMB
AAGjUzBRMB0GA1UdDgQWBBTH+uxCWs1TcDYNFptpXWMESc+MejAfBgNVHSMEGDAW
gBTH+uxCWs1TcDYNFptpXWMESc+MejAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
DQEBCwUAA4IBAQB6nHMSv+3rfO50t/e4pc613nIYbDv9/PnPouFwt8AiYk5ifpIa
WUZmupwY6Yl2JynzSHFFpe1afimd039LblUetlfDbv2Z+H4IBJ8lgCZE8GIskKNN
wpWF9Ovog0995fubUQdG9QU0JeCrlLDVlaDYhz1ImjP3KdOSZHZRWDdrzicwH6nQ
GZe0CgSML4S/YMPX/1BiEawpugcnAbDW3ZPh0md9FlsNt/rdL1PZiv0y9PM9cd8k
mqfVgPD7OAwihrjGVzFtmKzis0PbNpaydmpzII1j8OaHc8lLMSpIuGykbrfocD3O
p7zJ6bVvpr9PohKjIbslj2gkrMb7gq9EH4Tv
MIIDNzCCAh+gAwIBAgIUeRbZ6wwayGbn2Ava8XTPh6reXu0wDQYJKoZIhvcNAQEL
BQAwKzELMAkGA1UEBhMCVVMxHDAaBgNVBAMME1ZpcnR1QnJpY2stTG9jYWwtQ0Ew
HhcNMjIxMjI0MDQwNzM1WhcNMjUxMDEzMDQwNzM1WjArMQswCQYDVQQGEwJVUzEc
MBoGA1UEAwwTVmlydHVCcmljay1Mb2NhbC1DQTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAJdBvaTyxCo7+nJV3pSMVKFXc4VOLhlg0BZrAytZR64lC2jg
0JOI1qwQKeBRFKVN+ZsmfEOyIg82Hbtu+7ZzbvX1wKdcU/m9FT8JgEZ0rT8koN4C
S2idiTbNSiNXKkicbSjw6CfZEEL+LZaziR+Qt1hh/PMC6U5haz0bUtm8cKV1tfv8
aGs/GXyoZ35cUJq6YNWlE0Bxyt7LvEH7C/H5c2TIrUOLp+zTcMlWTxelkeBp51x9
cgOP5fILPOgs7IZ2wi8yUjfGBSfVWt6VyDp7vaws7/HozWta/tiGiLRImbulJeAw
BhPesBz6VUnaDeovHiwIFuFJHugPqv4TKNdXoOMCAwEAAaNTMFEwHQYDVR0OBBYE
FLo8qb1zkIVtEwu1whODHUf4Lq5dMB8GA1UdIwQYMBaAFLo8qb1zkIVtEwu1whOD
HUf4Lq5dMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADqVAf8P
aZ2M8YmmJnCxyKNmH1eeWwvPQB8+3H15auPDPXblqN48lw+pbN1dciBFlvpRSCEU
Ykdodo2W+Jyy1h8/zCVT4Vjz6OuQvKQSs/7sbxnx7txZ+3UTf0JJELXhyYtn4Sx+
+z9IjULy2zy+8QgK7c/QliBCXkTgStg0NayNhqVNM9lKAphpYJM99cgdiW7Mun+R
hMFj/QORCMOKGNYsR3ktlYPzXb8qzGhgX94RAY8wYfRtqCXbOq+Mpi8BRNF2G/0n
n+Pay/7yfdhiTtORrSjewsjSTElS9QzXrk26PreWWJWTAYuPa6l09Vxd4r8bYcqa
Nk9CdC6FVWP6x/I=
-----END CERTIFICATE-----

View File

@ -4,6 +4,6 @@ keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = gtoria.local
DNS.3 = *.gtoria.local
DNS.4 = *.*.gtoria.local
DNS.2 = virtubrick.local
DNS.3 = *.virtubrick.local
DNS.4 = *.*.virtubrick.local

4
etc/cert/gen.bat Normal file
View File

@ -0,0 +1,4 @@
openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout RootCA.key -out RootCA.pem -subj "/C=US/CN=VirtuBrick-Local-CA"
openssl x509 -outform pem -in RootCA.pem -out RootCA.crt
openssl req -new -nodes -newkey rsa:2048 -keyout vbrick.key -out vbrick.csr -subj "/C=US/ST=California/L=San Mateo/O=VirtuBrick Local Test/CN=virtubrick.local"
openssl x509 -req -sha256 -days 1024 -in vbrick.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile domains.ext -out vbrick.crt

View File

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIID0TCCArmgAwIBAgIUbUj9EBw3CYxjAyrsJy1LVn6r0q0wDQYJKoZIhvcNAQEL
BQAwMzELMAkGA1UEBhMCVVMxJDAiBgNVBAMMG0dyYXBoaWN0b3JpYS1EZXZlbG9w
bWVudC1DQTAeFw0yMjA0MTUwMjM1NTNaFw0yNTAyMDIwMjM1NTNaMG4xCzAJBgNV
BAYTAlVTMRIwEAYDVQQIDAlZb3VyU3RhdGUxETAPBgNVBAcMCFlvdXJDaXR5MSEw
HwYDVQQKDBhHcmFwaGljdG9yaWEtRGV2ZWxvcG1lbnQxFTATBgNVBAMMDGd0b3Jp
YS5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALYo89k+V6a9
VX2BiMEiRQbRuqxYbhcafI5Pr1eUuv99IFuHFUV/fA5QiQ3j9woTr3/VdURkr4C0
ZWjEW4yd+8p+PjM/vAx9LZp2zhYyGu9wa+fsciOXmF0zhC6nuSIhcLlHwInwJ0cv
SabXV59GmoC9zxe0xoreSAU6hggLfuEXifn0dfdJTcXwfYgrneYr7ZFS/f0lCuEh
T19/FLBChw0Hch9axPJM1N1OGmUQxPx0NJTEOp7GGTjq1VlOTpnEx+OdpWBIb0JN
fFlpDkWGD53lnf/fhio68wz9hsIv+XyNXfw7XPa1AkZWVnoTZNxwcJKC0ltVxwUG
h/uvJpi9gvUCAwEAAaOBoTCBnjAfBgNVHSMEGDAWgBTH+uxCWs1TcDYNFptpXWME
Sc+MejAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBEBgNVHREEPTA7gglsb2NhbGhv
c3SCDGd0b3JpYS5sb2NhbIIOKi5ndG9yaWEubG9jYWyCECouKi5ndG9yaWEubG9j
YWwwHQYDVR0OBBYEFIL06aX5T1tU7ozj1wC46e4qNW3wMA0GCSqGSIb3DQEBCwUA
A4IBAQBTZt4Pw6rzRNMPoPVOeAheLcd1JbO4Z+H3LW9MTerOp0JuaU7Q/LSbBBEp
/sP6aXzaIuepkiZk/pFlaXxDZ/XXrBy0sxGvMRI3K1hgU8evN3tiwTmLz1Vs2ffF
QEVUT3ytVxa/wP2A4uDhpZqqNjKvlxYesqXnSO7B20uO2IyYjliDwG1/dK6b6N64
XerbG+/sWjsNlpHLDu5qz7YYV78F6LO1bT24uVTWToXFFGuoJsf+3WrGp5Fg2RwN
FPBvLd+HbjWnkKN3BoMGP1fodAHTRhkiNOH3xMAOi4kxzArmxfg4gF+ABu6NO+67
iCBnuBC+ZyIkc24xsajDuU4csSho
-----END CERTIFICATE-----

View File

@ -1,17 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICszCCAZsCAQAwbjELMAkGA1UEBhMCVVMxEjAQBgNVBAgMCVlvdXJTdGF0ZTER
MA8GA1UEBwwIWW91ckNpdHkxITAfBgNVBAoMGEdyYXBoaWN0b3JpYS1EZXZlbG9w
bWVudDEVMBMGA1UEAwwMZ3RvcmlhLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAtijz2T5Xpr1VfYGIwSJFBtG6rFhuFxp8jk+vV5S6/30gW4cV
RX98DlCJDeP3ChOvf9V1RGSvgLRlaMRbjJ37yn4+Mz+8DH0tmnbOFjIa73Br5+xy
I5eYXTOELqe5IiFwuUfAifAnRy9JptdXn0aagL3PF7TGit5IBTqGCAt+4ReJ+fR1
90lNxfB9iCud5ivtkVL9/SUK4SFPX38UsEKHDQdyH1rE8kzU3U4aZRDE/HQ0lMQ6
nsYZOOrVWU5OmcTH452lYEhvQk18WWkORYYPneWd/9+GKjrzDP2Gwi/5fI1d/Dtc
9rUCRlZWehNk3HBwkoLSW1XHBQaH+68mmL2C9QIDAQABoAAwDQYJKoZIhvcNAQEL
BQADggEBAA/DMwmDDB989uhYGgpBiFENiqQBV4ApyWVSpf4p+egdVTgoa/1v1k2w
5dy2/z0x/MCzS+LTb8vwHoRXPWhLGerSXP5MgLtGWgFVrBvdfJ1QZCEc6OpihqFh
xHzKPD9Wbr3B9shUFURIsvl5qCYzwoePHPsEyrrgvF9wkmjV6ENJfIkaIi2U2ll6
H76GF3tN3ybR+NBcvRyc/xl+P8Hac4XAhvMNlDIvuFFvIMiZREnguoU0MSscSH61
3eJKZqGJx4kf81RXZw7bdAGG/OGfmF77s9EhBtxxGGKu6xcyfCzhdn0X1NsMvJXD
zIYiOCaou7k8Yu2A3VsLMsgLAV4PcH4=
-----END CERTIFICATE REQUEST-----

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2KPPZPlemvVV9
gYjBIkUG0bqsWG4XGnyOT69XlLr/fSBbhxVFf3wOUIkN4/cKE69/1XVEZK+AtGVo
xFuMnfvKfj4zP7wMfS2ads4WMhrvcGvn7HIjl5hdM4Qup7kiIXC5R8CJ8CdHL0mm
11efRpqAvc8XtMaK3kgFOoYIC37hF4n59HX3SU3F8H2IK53mK+2RUv39JQrhIU9f
fxSwQocNB3IfWsTyTNTdThplEMT8dDSUxDqexhk46tVZTk6ZxMfjnaVgSG9CTXxZ
aQ5Fhg+d5Z3/34YqOvMM/YbCL/l8jV38O1z2tQJGVlZ6E2TccHCSgtJbVccFBof7
ryaYvYL1AgMBAAECggEAB97gcmGG3gB47NGnpq35YjW2UB4IsQeG8YswiKM3f98t
17vlcmRIvZbt5Q4VgszznJ1iJ2YGTemoJreykPJ+ikhGyGYXlPPlADM5QleV4a9E
1PeFaFOeKgtrdFdGNjBQXjZjHlKkZSdTklmO7VCFT8y5DE2A9UfCFYpqzMwvsOqw
YA/EZdQvswnDScG8Dfu5kOGB/qAxrNGLrXcefCbYpubXBfs/duYcJ2uadTLa79sj
AK878G6Ql9LkiXx/yyq0LnUQqA0zrQeJMF9CEdNLA6O1n9BRjO9kKcR0LspKa2vp
Ygi4ISzgwJ5oR7iABcj3o/Tv2cmLdlSJp0DRuygFgQKBgQDtQl/m3Ic/7xQ/efN+
V6vPUCF/lXfw2Ep/qE5oEasCUqvcmeBOrqB8Uprl0dnLCxDz5c1jDnDaxeJpN9L7
RjHGLxqIV7F3ZfCn+neI3Ju0vbzTGkCcs6C1cbgTfrF9flgirkfR+cB0peWhEA/g
poAQW9X+jnOl3m+9JHtflpdcYQKBgQDEjGngPD7yk53c4duf7b+Im594EIHzZlv+
uczXHbP75/AwOPCsQPBycL7J0sWnsw+jyOOuCY1aj4b1VUBD1kGrgN4zziuHtMaV
wgStbAwAJOSaPcWaXXmQpTC4u9eTX7nnvnezri5E3XrnToUfK9B7+aEAZT39XHiZ
ItwOAnFPFQKBgC30i0rWMERL9KoO3wD7zkWLidGCjAbUfimX2ggCVBNRHATQsUfM
Pz2VandVXFAdxpzXSB8FrwpRBffHXlBZWk6+1O7PvYoY7rI6q2iRAn/RuH9TOGyh
xmEes77i7VIXZM7i3vpm28Y8U+wMhmbHGUsR3rM9uFzKZu5F4Le1HYBBAoGAL8lr
3IcJTvUxBokrWsD1NoOPzCNHVSRn7ZDDCvI/1llX/oF5koffbhOXb359a/6PKOUo
5iGQappG19M4YsXvBYG5hKL11nLPbY3UkU2ZxVcy9YVbS+K6Mb7YD7IsAbreekfG
1rrcqQWoYiCnISMH93yD9pKm9bjL4X+mPQm+/tkCgYEAjwdfAFSYnzUdxB8zTsXx
+p2daNJlY00YK0kf//qg4WhXkW6//jILoJFOD8lFMaVz+H30bGsHtOqAoTZ/+Ozk
Jwzlie9J2gWrInXu9zqnw2jAfIQZGZRFMNpxOoRT3yvh2fnArIXKtBdP107p2yLl
2w2vr0QHVij28jWQpsRGG0U=
-----END PRIVATE KEY-----

23
etc/cert/vbrick.crt Normal file
View File

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID2DCCAsCgAwIBAgIUSs0NnP/ZRmvsjJWv0ULFldiMwfowDQYJKoZIhvcNAQEL
BQAwKzELMAkGA1UEBhMCVVMxHDAaBgNVBAMME1ZpcnR1QnJpY2stTG9jYWwtQ0Ew
HhcNMjIxMjI0MDQwNzM4WhcNMjUxMDEzMDQwNzM4WjBxMQswCQYDVQQGEwJVUzET
MBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU2FuIE1hdGVvMR4wHAYDVQQK
DBVWaXJ0dUJyaWNrIExvY2FsIFRlc3QxGTAXBgNVBAMMEHZpcnR1YnJpY2subG9j
YWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjIun15WSkYDojtmUM
TOhSvCNZiMFADx7SFtZ9BmT94aURmJkQ/OU9vEBiaPBigNaByNEjp9FyKK+oCbgC
zdZjCtHnYeOTKpK8huHYFM0PE5MmMmmEf0M6ERrSpJ0IjAjoOhBC6iz3ouDeaRaa
Ha9GuB54RF1Jo4e0nX5A8OcUuzZA1DTdlZ1wrRFymgsjYPqE9b1If9Ni9ABehlNA
+6BUtwuef1jEyKTyXSd9hK/ngo2t/wKurxsjOOZiaNDZjdY0btGVSMQS0pqxVpiz
DI7RqqkdbRhHe/3hGKvCPXs0p6RjXINKeY6lhI+Tv3qogpnHqjfrnN/mfJMt7NW2
D9VJAgMBAAGjga0wgaowHwYDVR0jBBgwFoAUujypvXOQhW0TC7XCE4MdR/gurl0w
CQYDVR0TBAIwADALBgNVHQ8EBAMCBPAwUAYDVR0RBEkwR4IJbG9jYWxob3N0ghB2
aXJ0dWJyaWNrLmxvY2FsghIqLnZpcnR1YnJpY2subG9jYWyCFCouKi52aXJ0dWJy
aWNrLmxvY2FsMB0GA1UdDgQWBBQIQHg8iyx/ED9q8mtu9VKSPxBwYzANBgkqhkiG
9w0BAQsFAAOCAQEAKmwhDHvhytS81dDOWjzYXaQXzxOn3/6NSuL0FogY2sM8Nt3L
cT9JQQqqxevG2vbnUrODC2eGMSApnoBI1mJuP2SkyZGCVbi1QLca5WII/We/HPAs
OaC6CLKs1ywpClBV0GoFO7aNWEtSbQ0haNiGoEQsk8kvPFA3kLSCUF3SN0csFOc4
vcU8GwqrbO53hpclP3SZrwjzh1VlW985EMaWGd14/e/ASYu/+FSnIjbkZmha8CXu
8dI8BPAZ6D0nVj4kBICEy3bonzdJP/MhentCrE6WH2Eg5SqA2a14sSVx5K025OmS
QLjrqRLxlwMGYC+pQ+RHPmAl/ZVrJc7vli4CsA==
-----END CERTIFICATE-----

17
etc/cert/vbrick.csr Normal file
View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICtjCCAZ4CAQAwcTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx
EjAQBgNVBAcMCVNhbiBNYXRlbzEeMBwGA1UECgwVVmlydHVCcmljayBMb2NhbCBU
ZXN0MRkwFwYDVQQDDBB2aXJ0dWJyaWNrLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAoyLp9eVkpGA6I7ZlDEzoUrwjWYjBQA8e0hbWfQZk/eGl
EZiZEPzlPbxAYmjwYoDWgcjRI6fRciivqAm4As3WYwrR52HjkyqSvIbh2BTNDxOT
JjJphH9DOhEa0qSdCIwI6DoQQuos96Lg3mkWmh2vRrgeeERdSaOHtJ1+QPDnFLs2
QNQ03ZWdcK0RcpoLI2D6hPW9SH/TYvQAXoZTQPugVLcLnn9YxMik8l0nfYSv54KN
rf8Crq8bIzjmYmjQ2Y3WNG7RlUjEEtKasVaYswyO0aqpHW0YR3v94Rirwj17NKek
Y1yDSnmOpYSPk796qIKZx6o365zf5nyTLezVtg/VSQIDAQABoAAwDQYJKoZIhvcN
AQELBQADggEBAH9T2qdl5mWAEkNh0mHc7io7EqKCAwGSkWudj+QqWse9cn3AELLv
VbXUcE/GkcCTYiLyY8mJxwYaGiRa/tLcl4IHgXtG/a4oAoMdB5moQorT9YiWlXrs
3bzl/vZJaSmp12k2gN0Mu8H4ED5Eg4trKIcORzRsQV6zzYhF/4oUllr3cFg30CCl
nm7Mwwk6k4yB/zNuoPm6laukeMi99TLQ8LK57odi4Wqz4mZvd5lryhGEm6dZ6Cz+
Cahdba8vzvN3RIAWMhDubMxNfaAQvV1Z0yEZ6fcmEDWzof1tD1VtA82al5YJvLy3
RZcycbaB90F0XUhb20iElnxzig2XDNcbWR0=
-----END CERTIFICATE REQUEST-----

28
etc/cert/vbrick.key Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCjIun15WSkYDoj
tmUMTOhSvCNZiMFADx7SFtZ9BmT94aURmJkQ/OU9vEBiaPBigNaByNEjp9FyKK+o
CbgCzdZjCtHnYeOTKpK8huHYFM0PE5MmMmmEf0M6ERrSpJ0IjAjoOhBC6iz3ouDe
aRaaHa9GuB54RF1Jo4e0nX5A8OcUuzZA1DTdlZ1wrRFymgsjYPqE9b1If9Ni9ABe
hlNA+6BUtwuef1jEyKTyXSd9hK/ngo2t/wKurxsjOOZiaNDZjdY0btGVSMQS0pqx
VpizDI7RqqkdbRhHe/3hGKvCPXs0p6RjXINKeY6lhI+Tv3qogpnHqjfrnN/mfJMt
7NW2D9VJAgMBAAECggEABDCrSFAUiWF/v/2sbPT0Vw+snsOaJxf17cwW+HSEfb4U
D2m9rYe5Wzngs3mVI9dbhLWqPYHoqZR6Jbt3xcaqSRzBiHGYtuWpVpZ/6lA0D70s
ErD8lqHukZxX3CCZq4460/Anc8VWoCOt8x7i4DsYwem/vc1C673IbtV7i5Wq2C4h
e9rTlYE87D7mHfCIFwlV4JOqkqPYbR6sr8cf5rdAdy5L73bU/0ff4+TwY9UxnufM
crdvhf2nWJIQHh7zCfQapFTwUIlrsyAu6t30lRkdxNje2JVxpPDaEqHnDh/Nuni5
m4t4OUXZTvLhWblIIw5iwX/M9le9MmobHWSu5odd2wKBgQDcRh/DRv57adXInweX
AVL599H1LywjQAI/2eOV9BghBHb1Ln2LTidUS59pap+RZ2NL2OnKHhDX8u1UJi2G
DGibOHQep9pE56Gq/u1WJMpKnetIGr/hMSn7Uglg01BzmopiJ5OyN3cO7KdXH71J
oySKjISI7m0D+yrp93/O74YDgwKBgQC9mGmdBKYfv3sNYwoAQFCwKKcFYxlmaY5V
u7P1ViR0V+fkh7TW844FLXtI8cI9EbE3r6huM0YMlmL6fXb1zVoQgJUtT87pTMIf
ZcAq3kzHwkIA3vwFGZ8B1MsOKDybN379a8Ev3FM+Afyr1lrv/B4L14ZWcK2QbsNi
NJ3M2HlOQwKBgDdEFNYO6uyV+kByvhnCCEqVRgVpR360oZvZlENcUe1+zEXp2y/n
dPCuZJmzWcPGl+BA1S+T6Y/08FzLk2JtnJVNTb0fSiE9qI9ZlLynUGX2R0D5DSl4
B1t6EsZLXoUSwiOsYF83kVSaRcYTPY/LMfDdHqeogoucKgE3ysZlzE73AoGAT3dr
hPmm25W5cOH7FiHe8AcKAnMH+Wny07Jp+kHR48XYl2vd+154P2lRzEAwpsIconeI
xC/Pg4UhFVazHtGkl1gdrrFNy3F1yA0w34bvbabZXV4ZCdY0VGMpfNSWmoRHQNcC
URoq9cmFa0zcLsxgl5wNXXu689fJIwdkwLBXH9sCgYB52keZwt6rRu6n1q03tFWV
hZzxpxHX1hlw3jtLvWERpF8gLp5CRwX9xoMTciS82f3W/AUBx+eIiQ1HOUJ5W1S1
3GJBqCkWD8oipPxVW9XvKCdRHiY+2Jc+dKN2KTHjZSZLWDAZYkHL3/LC+gmQhM5j
bIyBpf2Yn45e1NIxAngLCw==
-----END PRIVATE KEY-----

View File

@ -1,9 +1,11 @@
APP_NAME=Graphictoria
APP_NAME=VirtuBrick
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://gtoria.net
MIX_APP_URL=http://gtoria.net
APP_URL=http://virtubrick.net
MIX_APP_URL=http://virtubrick.net
IS_TEST_ENVIRONMENT=true
GAMESERVER_IP=127.0.0.1
THUMBNAILER_IP=127.0.0.1
@ -18,7 +20,7 @@ RECAPTCHA_SECRET_KEY=ServerKeyHere
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=gtoria
DB_DATABASE=virtubrick
DB_USERNAME=root
DB_PASSWORD=

View File

@ -5,7 +5,7 @@ COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=node /usr/local/bin/node /usr/local/bin/node
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm
WORKDIR /gtoria
WORKDIR /vbrick
COPY . .

View File

@ -1,7 +1,7 @@
<?php
/*
Graphictoria 2022
XlXi 2022
This file handles communications between the arbiter and the website.
*/

View File

@ -1,7 +1,7 @@
<?php
/*
Graphictoria 2022
XlXi 2022
CDN helper.
*/

View File

@ -1,7 +1,7 @@
<?php
/*
Graphictoria 2022
XlXi 2022
Domain helper.
*/

View File

@ -1,7 +1,7 @@
<?php
/*
Graphictoria 2022
XlXi 2022
Grid helper
*/

View File

@ -1,7 +1,7 @@
<?php
/*
Graphictoria 2022
XlXi 2022
Maintenance helper
*/
@ -14,8 +14,8 @@ class MaintenanceHelper
{
public static function isDown()
{
if(GridHelper::hasAllAccess())
return true;
if(GridHelper::isIpWhitelisted())
return false;
if(!file_exists(storage_path('framework/down')))
return false;
@ -30,9 +30,9 @@ class MaintenanceHelper
$request = request();
return isset($data['secret']) &&
$request->cookie('gt_constraint') &&
$request->cookie('vb_constraint') &&
MaintenanceModeBypassCookie::isValid(
$request->cookie('gt_constraint'),
$request->cookie('vb_constraint'),
$data['secret']
);
}

View File

@ -1,7 +1,7 @@
<?php
/*
Graphictoria 2022
XlXi 2022
A bit of a hacky way to implement markdown with laravel.
*/

View File

@ -1,7 +1,7 @@
<?php
/*
Graphictoria 2022
XlXi 2022
Number helper.
*/

View File

@ -1,7 +1,7 @@
<?php
/*
Graphictoria 2022
XlXi 2022
Quick Administration and Management Bar helper
*/

View File

@ -1,7 +1,7 @@
<?php
/*
Graphictoria 2022
XlXi 2022
Validation Helper
*/

View File

@ -9,230 +9,8 @@ class ApiController extends Controller
{
public function index()
{
$apiTxts = [
<<<EOT
+##################+
| A. Mayonnaise |
| P. On |
| I. An |
| Escalator |
+##################+
| (its goin |
| upstairs so |
| see ya later) |
+##################+
| bye bye! |
+##################+
EOT,
<<<EOT
/ This is bob. Copy and paste him so he can take over Graphictoria.
/
/\
EOT,
<<<EOT
░░░░░░░▐▀█▀▌░░░░▀█▄░░░░
░░░░░░░▐█▄█▌░░░░░░▀█▄░░
░░░░░░░░▀▄▀░░░▄▄▄▄▄▀▀░░
░░░░░░▄▄▄██▀▀▀▀░░░░░░░░
░░░░░█▀▄▄▄█░▀▀░░░░░░░░░
░░░░░▌░▄▄▄▐▌▀▀▀░░░░░░░░
░░▄░▐░░░▄▄░█░▀▀ ░░░░░░░
░░▀█▌░░░▄░▀█▀░▀ ░░░░░░░
░░░░░░░░░▄▄▐▌▄▄░░░░░░░░
░░░░░░░░░▀███▀█░▄░░░░░░
░░░░░░░░▐▌▀▄▀▄▀▐▄░░░░░░
░░░░░░░░▐▀░░░░░░▐▌░░░░░
░░░░░░░░█░░░░░░░░█░░░░░
░░░░░░░░█░░░░░░░░█░░░░░
░░░░░░░░█░░░░░░░░█░░░░░
░░░░░░ ▄██▄░░░░░ ▄██▄░░
EOT,
<<<EOT
——————————————No API?—————————————
⠀⣞⢽⢪⢣⢣⢣⢫⡺⡵⣝⡮⣗⢷⢽⢽⢽⣮⡷⡽⣜⣜⢮⢺⣜⢷⢽⢝⡽⣝
⠸⡸⠜⠕⠕⠁⢁⢇⢏⢽⢺⣪⡳⡝⣎⣏⢯⢞⡿⣟⣷⣳⢯⡷⣽⢽⢯⣳⣫⠇
⠀⠀⢀⢀⢄⢬⢪⡪⡎⣆⡈⠚⠜⠕⠇⠗⠝⢕⢯⢫⣞⣯⣿⣻⡽⣏⢗⣗⠏⠀
⠀⠪⡪⡪⣪⢪⢺⢸⢢⢓⢆⢤⢀⠀⠀⠀⠀⠈⢊⢞⡾⣿⡯⣏⢮⠷⠁⠀⠀
⠀⠀⠀⠈⠊⠆⡃⠕⢕⢇⢇⢇⢇⢇⢏⢎⢎⢆⢄⠀⢑⣽⣿⢝⠲⠉⠀⠀⠀⠀
⠀⠀⠀⠀⠀⡿⠂⠠⠀⡇⢇⠕⢈⣀⠀⠁⠡⠣⡣⡫⣂⣿⠯⢪⠰⠂⠀⠀⠀⠀
⠀⠀⠀⠀⡦⡙⡂⢀⢤⢣⠣⡈⣾⡃⠠⠄⠀⡄⢱⣌⣶⢏⢊⠂⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⢝⡲⣜⡮⡏⢎⢌⢂⠙⠢⠐⢀⢘⢵⣽⣿⡿⠁⠁⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠨⣺⡺⡕⡕⡱⡑⡆⡕⡅⡕⡜⡼⢽⡻⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⣼⣳⣫⣾⣵⣗⡵⡱⡡⢣⢑⢕⢜⢕⡝⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣴⣿⣾⣿⣿⣿⡿⡽⡑⢌⠪⡢⡣⣣⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⡟⡾⣿⢿⢿⢵⣽⣾⣼⣘⢸⢸⣞⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠁⠇⠡⠩⡫⢿⣝⡻⡮⣒⢽⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
—————————————————————————————————
EOT,
<<<EOT
⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⢿⢯⣛⣺⣯⣿⣿⣿⣿⣿⣿⣿⢱⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⡿⣿⣿⢡⣿⣉⣿⡿⠿⠿⠿⡿⠿⠻⣿⡇⠸⣻⠾⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⡿⠛⠉⠁⠹⡰⣹⣟⣧⣤⡤⠄⠄⠠⣡⣼⣷⠄⢉⢻⣿⣿⣿⣿⣿⣿⣿⣿
⣿⠟⠄⠄⠄⡀⢸⣾⣿⣯⣯⡃⠄⠄⠄⠄⠐⠙⣿⣧⡀⠩⣧⠙⣿⣿⣿⣿⣿⣿
⣿⠄⠄⠄⠈⠈⣾⣿⣿⣿⣿⣆⡀⠄⠄⠄⠄⠄⣸⣿⣿⣿⣧⠄⣼⣿⣿⣿⣿⣿
⣿⠇⠄⠄⠄⠄⠙⠛⠛⠿⠿⢿⣿⣶⣀⣶⣾⣿⣿⣿⣿⢾⣷⣇⣤⣿⣿⣿⣿⣿
⣿⣻⠄⠄⠄⠄⠄⠄⠄⠄⠠⠤⣤⣤⣌⠉⠉⠉⠁⢈⠁⠤⠛⣼⣿⣿⣿⣿⠿⠿
⠈⠈⠄⠄⠄⠄⣀⣴⡦⠴⠠⢠⣴⣶⣶⣶⣿⣿⡶⠛⠠⠄⠄⣿⣿⡿⠟⠁⠺⠿
⣀⣤⣤⣦⣤⣼⣿⡿⣣⣿⡷⣿⣿⣿⣿⣿⣿⡿⣿⡄⠄⠄⠄⢟⡁⠚⠦⠴⠤⣤
⠿⠉⠛⠟⣻⣿⠋⢁⣿⢿⣵⣭⣞⢿⣯⣽⣿⣿⣿⣿⡆⠄⠄⠄⠉⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠈⠁⠄⢯⣷⣿⣿⣯⡿⣽⣾⣿⣿⠿⢿⣿⣧⡄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⡴⢇⠉⢹⣀⣿⣿⣿⢿⡟⣿⣧⣼⡀⡩⠻⣦⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠰⠄⠣⣸⣶⠛⠛⠻⣿⡿⠿⢱⡟⠉⠉⠻⣿⡲⠃⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠒⠄⠈⠿⠄⠄⠄⡿⠃⠄⠘⠄⠄⢀⡠⠏⠄⠄⠄⠄⠄⠄⠄⠄⠄
EOT,
<<<EOT
summoning circle, hope this works!
🕯
🕯 🕯
🕯 🕯
🕯 graphictoria client 🕯
🕯 🕯
🕯 🕯
🕯
EOT,
<<<EOT
➖➖➖➖➖➖➖➖⬛⬛⬛➖➖➖➖➖➖➖➖➖
➖➖➖➖➖➖➖⬛⬛⬛⬛⬛➖➖➖➖➖➖➖➖
➖➖➖➖➖➖⬛⬛⬜⬜⬜⬛⬛➖➖➖➖➖➖➖
➖➖➖➖➖➖⬜⬜⬜⬜⬜⬜⬜⬛➖➖➖➖➖➖
➖➖➖➖➖⬛⬜⬜⬜⬜⬜⬜⬜⬛⬛➖➖➖➖➖
➖➖➖➖➖⬜⬜⬜⬜⬜⬜⬜⬜⬛⬛➖➖➖➖➖
➖➖➖➖⬛⬜⬜⬛⬛⬛⬜⬜⬛⬛⬛➖➖➖➖➖
➖➖➖➖⬛⬛⬛⬛⬜⬛⬜⬛⬛⬛⬛⬛➖➖➖➖
➖➖➖➖⬛⬛⬛⬜⬜⬜⬜⬛⬛⬛⬛⬛➖➖➖➖
➖➖➖⬜⬛⬛⬛⬛⬛⬜⬜⬛⬛⬛⬛⬛➖➖➖➖
➖➖⬜⬜⬜⬜⬜⬜⬜⬛⬜⬛⬛⬛⬛⬛➖➖➖➖
➖➖⬛⬛⬛⬜⬜⬜⬛⬜⬜⬛⬛⬛⬛⬛⬛➖➖➖
➖➖⬜⬛⬛⬜⬜⬛⬜⬜⬛⬛⬛⬛⬛⬛⬛➖➖➖
➖➖➖⬜⬜⬜⬜⬜⬜⬜⬜⬛⬛⬛⬜⬛⬛➖➖➖
➖➖➖➖⬜⬜⬜⬛⬛⬛⬛⬛⬜⬜⬜⬛⬛➖➖➖
➖➖➖➖⬜⬜⬜⬜⬜⬜⬜⬜⬛⬛⬛⬛⬛⬛➖➖
➖➖➖➖⬜⬜⬜⬜⬜⬜⬜⬜⬜⬛⬛⬛⬛⬛⬛➖
➖➖➖⬛⬛⬜⬜⬜⬜⬜⬜⬜⬜⬛⬛⬛⬛⬛⬛➖
➖➖⬛⬛⬛⬛⬜⬜⬜⬜⬜⬜⬛⬛⬛⬛⬛⬛⬛➖
EOT,
<<<EOT
⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠄⠄⠄⠄⠄⠄⠄⠄⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⠄⠄⢀⣀⣀⣀⡀⠄⢀⣠⡔⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣰⢿⣿⣿⣿⣿⣿⣿⣷⡆⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⣻⣟⣿⣿⡿⣟⣛⣿⡃⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣧⣿⣾⣿⣷⣿⣷⣿⣿⣿⣷⣽⣹⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⡟⣟⣿⣿⠺⣟⣻⣿⣿⣿⡏⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⡝⠻⠵⠿⠿⢿⣿⣿⢳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣧⠈⣛⣛⣿⣿⡿⣡⣞⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡧⠄⠙⠛⠛⢁⣴⣿⣿⣷⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⡿⠟⠉⠄⠄⢠⠄⣀⣠⣾⣿⣿⡿⠟⠁⠄⠈⠛⢿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⡟⠉⠄⠄⢀⠠⠐⠒⠐⠾⠿⢟⠋⠁⠄⢀⣀⠠⠐⠄⠂⠈⠻⢿⣿⣿
⣿⣿⣿⠋⠁⠄⢀⡈⠄⠄⠄⠄⠄⠄⠄⠄⠁⠒⠉⠄⢠⣶⠄⠄⠄⠄⠄⠈⠫⢿
⣿⣿⡟⠄⢔⠆⡀⠄⠈⢀⠄⠄⠄⠄⠄⠄⠄⢄⡀⠄⠈⡐⢠⠒⠄⠄⠄⠄⢀⣂
⣿⣿⠁⡀⠄⠄⢇⠄⠄⢈⠆⠄⠄⢀⠔⠉⠁⠉⠉⠣⣖⠉⡂⡔⠂⠄⢀⠔⠁⠄
⣿⡿⠄⠄⠄⠄⢰⠹⣗⣺⠤⠄⠰⡎⠄⠄⠄⠄⠄⠄⠘⢯⡶⢟⡠⠰⠄⠄⠄⠄
EOT,
<<<EOT
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢀⣶⣿⣿⣿⣿⣿⣿⣶⣆⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣸⣿⣿⠉⠉⠉⠄⠉⢹⣿⣦⡀⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢿⣿⣿⣁⠄⠄⠤⠤⡀⠻⣿⠃⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠘⣿⣿⣿⡗⠖⡶⢾⣶⠊⡏⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢻⣿⣿⣅⣈⠂⠐⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠘⢿⣾⣇⣂⣠⠄⠄⠄⠁⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢘⣿⣗⠒⠄⢨⠶⢁⣄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠨⣿⣿⡿⠋⠁⣴⣿⣿⣷⣦⣄⡀⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⢀⣠⣄⣶⣎⢱⢄⢀⣾⣿⣿⣿⣿⣿⣿⣿⣶⣦⣤⣄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⢠⣾⣿⣿⡞⢝⡟⠃⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣇⠄⠄⠄
⠄⠄⠄⠄⠆⢄⠄⢛⡫⠝⢿⡥⠟⡃⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣼⣭⣻⣿⣿⡀⠄⠄
⠄⠄⠄⣴⣆⠄⢋⠄⠐⣡⣿⣆⣴⣼⣿⣿⣿⣿⣿⣿⣿⣿⠏⢈⣿⣿⣿⣿⣿⣿⣷⡄⠄
⠄⠄⣼⣿⣷⠄⠉⠒⣪⣹⣟⣹⣿⣿⣿⣿⣿⣟⣿⣿⣿⡇⢀⣸⣿⣿⣿⢟⣽⣿⣿⣇⠄
EOT,
<<<EOT
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣶⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⠿⠟⠛⠻⣿⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣆⣀⣀⠀⣿⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠻⣿⣿⣿⠅⠛⠋⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢼⣿⣿⣿⣃⠠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣟⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣛⣛⣫⡄⠀⢸⣦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⡆⠸⣿⣿⣿⡷⠂⠨⣿⣿⣿⣿⣶⣦⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⣾⣿⣿⣿⣿⡇⢀⣿⡿⠋⠁⢀⡶⠪⣉⢸⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⡏⢸⣿⣷⣿⣿⣷⣦⡙⣿⣿⣿⣿⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣇⢸⣿⣿⣿⣿⣿⣷⣦⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⣵⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
EOT,
<<<EOT
⣿⣿⣿⣿⣿⣿⡿⠛⠋⠉⠄⠄⠄⠄⠄⠄⠄⠄⠄⠈⠉⠛⠿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⡿⠋⠁⠄⠄⢠⣴⣶⣿⣿⣶⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠈⠿⣿⣿⣿⣿
⣿⣿⡟⠁⠄⠄⠄⠄⣿⣿⣿⣿⣿⣿⣇⡀⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢹⣿⣿⣿
⣿⣿⣧⠄⠄⠄⠄⢰⣿⣿⣿⣿⣿⣿⣿⡆⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣸⣿⣿⣿
⣿⣿⣿⣧⡀⠄⠄⢸⣿⣿⣿⣿⣿⣿⣿⣷⣆⠄⠄⠄⠄⠄⠄⠄⠄⣰⣿⣿⣿⣿
⣿⣿⣿⣿⡿⣦⣀⣾⣿⣟⣉⠉⠙⢛⡏⠁⠄⠄⠄⠄⠄⠄⠄⠄⠚⢿⣿⣿⣿⣿
⣿⣿⣿⣿⣯⣗⣻⣿⣯⣥⣦⠄⣀⣾⡇⠄⠄⠂⠄⠄⠄⠄⠄⠄⠄⣼⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠄⠄⠂⠄⠄⠄⠄⠄⠄⠄⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣻⠋⠄⠄⠄⠄⠄⠄⠄⢀⠄⣸⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡁⡀⠄⠄⠄⠄⠄⠄⢸⣾⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣥⣾⣷⠶⠆⠄⠄⠄⢀⠄⠄⠄⠸⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⣿⣿⣿⣶⣄⡀⠄⠄⠄⠄⠄⢀⠄⠸⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⠟⠚⣿⣿⡻⠿⠿⠛⠙⠁⠄⠄⠄⠄⠠⠂⠄⠄⠘⠿⣿⣿⣿⣿
⠿⠛⠉⠁⠁⠄⠄⠄⣻⣿⣿⣧⣠⣀⠄⠄⠄⠄⡀⠂⠄⠄⠄⠄⠄⠄⠈⠉⠿⢿
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠘⠿⣿⡿⠃⢀⡠⠄⠃⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
EOT,
<<<EOT
⠀⠀⠀⠀⣠⣦⣤⣀
⠀⠀⠀⠀⢡⣤⣿⣿
⠀⠀⠀⠀⠠⠜⢾⡟
⠀⠀⠀⠀⠀⠹⠿⠃⠄
⠀⠀⠈⠀⠉⠉⠑⠀⠀⠠⢈⣆
⠀⠀⣄⠀⠀⠀⠀⠀⢶⣷⠃⢵
⠐⠰⣷⠀⠀⠀⠀⢀⢟⣽⣆⠀⢃
⠰⣾⣶⣤⡼⢳⣦⣤⣴⣾⣿⣿⠞
⠀⠈⠉⠉⠛⠛⠉⠉⠉⠙⠁
⠀⠀⡐⠘⣿⣿⣯⠿⠛⣿⡄
⠀⠀⠁⢀⣄⣄⣠⡥⠔⣻⡇
⠀⠀⠀⠘⣛⣿⣟⣖⢭⣿⡇
⠀⠀⢀⣿⣿⣿⣿⣷⣿⣽⡇
⠀⠀⢸⣿⣿⣿⡇⣿⣿⣿⣇
⠀⠀⠀⢹⣿⣿⡀⠸⣿⣿⡏
⠀⠀⠀⢸⣿⣿⠇⠀⣿⣿⣿
⠀⠀⠀⠈⣿⣿⠀⠀⢸⣿⡿
⠀⠀⠀⠀⣿⣿⠀⠀⢀⣿⡇
⠀⣠⣴⣿⡿⠟⠀⠀⢸⣿⣷
⠀⠉⠉⠁⠀⠀⠀⠀⢸⣿⣿⠁
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈
EOT,
<<<EOT
this is nsg
🤠
  🍺🍺🍺
🍺🍺🍺🍺🍺🍺
👇🏽  🍺🍺 👇🏽
  🍺 🍺
  🍺 🍺
  👢 👢
say hi to nsg
EOT,
<<<EOT
If you're wondering why all all of these random responses keep showing up, that is the magic of computer programming. A bored programmer(that's me!) decided they wanted to grab a bunch of ascii images off the internet and modify them to fit the theme of this site instead of doing code. Basically doing sweet F.A. on the job.
This is why the client took 2 years... THIS IS WHY. (graphictoria sunday btw)
Anyways, I applaud you for wasting probably minutes of your life to find this message, maybe skipped over it a few times while spamming CTRL + R, but still reached it eventually.
If this is your first time going to "api.gtoria.net", well; hm... Oh, I know! Erase everything you've seen here from your mind, and move on to doing something more productive. There's nothing at all to see on this here "api.gtoria.net" index page. Nothing at all!
EOT
];
// TODO: XlXi: Add some checks here, such as pinging api.gtoria.net, checking commonly used API functions, etc...
return response($apiTxts[array_rand($apiTxts)])
// TODO: XlXi: Add some checks here, such as pinging api.virtubrick.net, checking commonly used API functions, etc...
return response('API OK!')
->header('Content-Type', 'text/plain');
}
}

View File

@ -49,7 +49,7 @@ class CommentsController extends Controller
// TODO: XlXi: user profile link
$poster = [
'name' => $comment->user->username,
'thumbnail' => 'https://www.gtoria.local/images/testing/headshot.png',
'thumbnail' => 'https://www.virtubrick.local/images/testing/headshot.png',
'url' => $comment->user->getProfileUrl()
];

View File

@ -41,7 +41,7 @@ class FeedController extends Controller
$poster = [
'type' => 'User',
'name' => $user->username,
'thumbnail' => 'https://www.gtoria.local/images/testing/headshot.png',
'thumbnail' => 'https://www.virtubrick.local/images/testing/headshot.png',
'url' => $user->getProfileUrl()
];
}

View File

@ -0,0 +1,67 @@
<?php
namespace App\Http\Controllers\Api;
use Carbon\Carbon;
use Symfony\Component\HttpFoundation\Cookie;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Models\DynamicWebConfiguration;
use App\Helpers\ValidationHelper;
use App\Http\Controllers\Controller;
class MaintenanceController extends Controller
{
public function bypass(Request $request)
{
$validator = Validator::make($request->all(), [
'password' => ['required'],
'buttons' => ['required']
]);
if($validator->fails())
return ValidationHelper::generateValidatorError($validator);
$valid = $validator->valid();
$password = $valid['password'];
$buttons = $valid['buttons'];
$mtconf = json_decode(DynamicWebConfiguration::whereName('MaintenancePassword')->first()->value);
if(file_exists(storage_path('framework/down')) && $password == $mtconf->password)
{
$btns = array_slice($buttons, -count($mtconf->combination));
$data = json_decode(file_get_contents(storage_path('framework/down')), true);
if(isset($data['secret']) && $btns === $mtconf->combination)
{
$trustedHosts = explode(',', env('TRUSTED_HOSTS'));
$origin = join('.', array_slice(explode('.', explode('//', $request->headers->get('origin'))[1]), -2));
$passCheck = false;
foreach($trustedHosts as &$host)
{
if(str_ends_with($origin, $host))
$passCheck = true;
}
$expiresAt = Carbon::now()->addHours(24);
$bypassCookie = new Cookie('vb_constraint', base64_encode(json_encode([
'expires_at' => $expiresAt->getTimestamp(),
'mac' => hash_hmac('SHA256', $expiresAt->getTimestamp(), $data['secret']),
])), $expiresAt);
$bypassCookie = $bypassCookie->withSameSite('none');
if($passCheck)
$bypassCookie = $bypassCookie->withDomain('.' . $origin);
return response('')
->withCookie($bypassCookie);
}
}
$validator->errors()->add('password', 'Bad Request.');
return ValidationHelper::generateValidatorError($validator);
}
}

View File

@ -6,6 +6,8 @@ use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\DynamicWebConfiguration;
use App\Models\User;
use App\Models\UserIp;
class AdminController extends Controller
{
@ -20,11 +22,60 @@ class AdminController extends Controller
}
// Moderator+
// GET admin.dashboard
function dashboard()
{
return view('web.admin.dashboard');
}
// GET admin.usersearch
function userSearch()
{
return view('web.admin.usersearch');
}
// POST admin.usersearch
function userSearchQuery(Request $request)
{
if($request->has('userid-button'))
{
$request->validate([
'userid-search' => ['required', 'int']
]);
return view('web.admin.usersearch')->with('users', User::where('id', $request->get('userid-search'))->get());
}
if($request->has('username-button'))
{
$request->validate([
'username-search' => ['required', 'string']
]);
return view('web.admin.usersearch')->with('users', User::where('username', 'like', '%' . $request->get('username-search') . '%')->get());
}
if($request->has('ipaddress-button'))
{
$request->validate([
'ipaddress-search' => ['required', 'ip']
]);
$result = UserIp::where('ipAddress', $request->get('ipaddress-search'))
->join('users', 'users.id', '=', 'user_ips.userId')
->orderBy('users.id', 'desc');
return view('web.admin.usersearch')->with('users', $result->get())->with('isIpSearch', true);
}
return view('web.admin.usersearch')->with('error', 'Input validation failed.');
}
// GET admin.autoupload
function autoUpload()
{
return view('web.admin.autoupload');
}
// Admin+
function metricsVisualization()
{

View File

@ -0,0 +1,16 @@
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class MaintenanceController extends Controller
{
public function index()
{
$data = json_decode(file_get_contents(storage_path('framework/down')), true);
return view('web.maintenance', ['hideLogin' => !isset($data['secret'])]);
}
}

View File

@ -19,7 +19,7 @@ class TestController extends Controller
// mrgrey = https://www.roblox.com/asset/?id=1785197
$test = new SoapService('Thumbnail');
$result = $test->OpenJob(GridHelper::JobTemplate('test', 10, 0, 0, 'test render', 'place', ['http://www.roblox.com/asset/?id=444204653', 'PNG', 1920, 1080, 'https://www.gtoria.local/', 169618721]));
$result = $test->OpenJob(GridHelper::JobTemplate('test', 10, 0, 0, 'test render', 'place', ['http://www.roblox.com/asset/?id=444204653', 'PNG', 1920, 1080, 'https://www.virtubrick.local/', 169618721]));
return response(base64_decode($result->OpenJobExResult->LuaValue[0]->value))
->header('Content-Type', 'image/png');

View File

@ -0,0 +1,14 @@
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class TestSiteController extends Controller
{
public function info()
{
return view('web.testing.info');
}
}

View File

@ -23,7 +23,6 @@ class Kernel extends HttpKernel
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
@ -39,6 +38,8 @@ class Kernel extends HttpKernel
'csrf',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
// XlXi: Yeah no, the double session protector was stupid.
//\App\Http\Middleware\DoubleSessionProtector::class, // Prevents DDoS attacks.
\App\Http\Middleware\DailyReward::class,
@ -46,6 +47,8 @@ class Kernel extends HttpKernel
],
'api' => [
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],

View File

@ -7,6 +7,8 @@ use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\UserIp;
class LastSeenMiddleware
{
/**
@ -23,6 +25,8 @@ class LastSeenMiddleware
$user->last_seen = Carbon::now();
$user->timestamps = false;
$user->save();
$user->saveIp($request->ip());
}
return $next($request);

View File

@ -2,16 +2,48 @@
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
use App\Helpers\MaintenanceHelper;
class PreventRequestsDuringMaintenance extends Middleware
use Closure;
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;
class PreventRequestsDuringMaintenance
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array<int, string>
*/
protected $except = [
//
];
public function handle(Request $request, Closure $next)
{
if(MaintenanceHelper::isDown($request))
{
if(str_starts_with($request->route()->getName(), 'maintenance.'))
return $next($request);
if(in_array('api', $request->route()->middleware()))
{
if($request->route()->getName() == 'content') // cdn.virtubrick.net
return $next($request);
return response(['errors' => [['code' => 503, 'message' => 'ServiceUnavailable']]], 503)
->header('Cache-Control', 'private')
->header('Content-Type', 'application/json; charset=utf-8');
}
// Not an API route.
if($request->route()->uri() != 'maintenance')
return redirect('/maintenance?ReturnUrl=' . urlencode(url()->full()));
}
else
{
if(str_starts_with($request->route()->getName(), 'maintenance.'))
{
$returnUrl = $request->input('ReturnUrl');
if(!$returnUrl)
$returnUrl = '/';
return redirect($returnUrl);
}
}
return $next($request);
}
}

View File

@ -55,15 +55,15 @@ class AppDeployment implements ShouldQueue
switch($this->deployment->app)
{
case 'client':
$appArchive = 'Graphictoria.zip';
$appName = 'GraphictoriaPlayer.exe';
$bootstrapperName = 'GraphictoriaPlayerLauncher.exe';
$appArchive = 'VirtuBrick.zip';
$appName = 'VirtuBrickPlayer.exe';
$bootstrapperName = 'VirtuBrickPlayerLauncher.exe';
$bootstrapperVersionName = 'BootstrapperVersion.txt';
break;
case 'studio':
$appArchive = 'GraphictoriaStudio.zip';
$appName = 'GraphictoriaStudio.exe';
$bootstrapperName = 'GraphictoriaStudioLauncherBeta.exe';
$appArchive = 'VirtuBrickStudio.zip';
$appName = 'VirtuBrickStudio.exe';
$bootstrapperName = 'VirtuBrickStudioLauncherBeta.exe';
$bootstrapperVersionName = 'BootstrapperQTStudioVersion.txt';
break;
}

View File

@ -2,6 +2,7 @@
namespace App\Jobs;
use claviska\SimpleImage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
@ -83,10 +84,10 @@ class ArbiterRender implements ShouldQueue
{
// TODO: XlXi: User avatar/closeup render support.
$arguments = [
url(sprintf('/asset?id=%d', $this->assetId)), // TODO: XlXi: Move url() to route() once the route actually exists.
route('client.asset', ['id' => $this->assetId]),
($this->is3D ? 'OBJ' : 'PNG'),
840, // Width
840, // Height
420*4, // Width // XlXi: These get scaled down by 4.
420*4, // Height // XlXi: These get scaled down by 4.
url('/') . '/'
];
switch($this->type) {
@ -177,7 +178,13 @@ class ArbiterRender implements ShouldQueue
$this->tracker->targetObj->set3DHash(CdnHelper::SaveContent(json_encode($result), 'text/plain'));
} else {
$this->tracker->targetObj->set2DHash(CdnHelper::SaveContentB64($result, 'image/png'));
$image = new SimpleImage();
$image = $image
->fromString(base64_decode($result))
->resize($arguments[2]/4, $arguments[3]/4)
->toString();
$this->tracker->targetObj->set2DHash(CdnHelper::SaveContentB64(base64_encode($image), 'image/png'));
}
$this->tracker->delete();

View File

@ -48,6 +48,7 @@ class User extends Authenticatable implements MustVerifyEmail
protected $casts = [
'email_verified_at' => 'datetime',
'next_reward' => 'datetime',
'created_at' => 'datetime',
'last_seen' => 'datetime',
];
@ -91,6 +92,17 @@ class User extends Authenticatable implements MustVerifyEmail
return $this->created_at->isoFormat('ll');
}
public function getCensoredEmail()
{
$email = $this->email;
$bits = explode('@', $email);
$name = implode('@', array_slice($bits, 0, count($bits) - 1));
$length = floor(strlen($name) / 2);
return substr($name, 0, $length) . str_repeat('*', $length) . "@" . end($bits);
}
// XlXi: TODO: Replace this with detailed presence
// like what game the user is in or
// what place they're editing.
@ -99,6 +111,27 @@ class User extends Authenticatable implements MustVerifyEmail
return ($this->last_seen >= Carbon::now()->subMinutes(2));
}
public function getRolesets()
{
return UserRoleset::where('User_id', $this->id);
}
public function saveIp($ip)
{
$ipExists = UserIp::where('userId', $this->id)
->where('ipAddress', $ip)
->exists();
if(!$ipExists)
{
return UserIp::create([
'userId' => $this->id,
'ipAddress' => $ip
]);
}
return false;
}
public function _hasRolesetInternal($roleName)
{
$roleset = Roleset::where('Name', $roleName)->first();

26
web/app/Models/UserIp.php Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class UserIp extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'userId',
'ipAddress'
];
public function user()
{
return $this->belongsTo(User::class, 'userId');
}
}

View File

@ -128,7 +128,7 @@ class Asset extends Model
$thumbnail = Http::get(route('thumbnails.v1.asset', ['id' => $renderId, 'type' => '2d']));
if($thumbnail->json('status') == 'loading')
return ($this->assetTypeId == 9 ? 'https://gtoria.local/images/busy/game.png' : 'https://gtoria.local/images/busy/asset.png');
return ($this->assetTypeId == 9 ? 'https://virtubrick.local/images/busy/game.png' : 'https://virtubrick.local/images/busy/asset.png');
return $thumbnail->json('data');
}

View File

@ -44,7 +44,7 @@ class ResetPasswordNotification extends Notification
*/
public function toMail($notifiable)
{
$title = 'Graphictoria Password Reset';
$title = config('app.name') . ' Password Reset';
return (new MailMessage)
->subject($title)

View File

@ -37,6 +37,14 @@ class AppServiceProvider extends ServiceProvider
return get_class($validator) != UriValidator::class;
});
Blade::directive('nonav', function() {
return '<?php $noNav=true; ?>';
});
Blade::directive('nofooter', function() {
return '<?php $noFooter=true; ?>';
});
Blade::directive('owner', function() {
return '<?php if(Auth::check() && Auth::user()->hasRoleset(\'Owner\')): ?>';
});

View File

@ -32,7 +32,7 @@ class RouteServiceProvider extends ServiceProvider
$this->routes(function () {
//
// Domain: gtoria.net
// Domain: virtubrick.net
//
Route::domain(DomainHelper::TopLevelDomain())
->middleware('web')
@ -40,7 +40,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/web.php'));
//
// Domain: www.gtoria.net
// Domain: www.virtubrick.net
//
Route::domain('www.' . DomainHelper::TopLevelDomain())
->middleware('web')
@ -48,7 +48,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/web.php'));
//
// Domain: www.gtoria.net
// Domain: www.virtubrick.net
//
Route::domain('blog.' . DomainHelper::TopLevelDomain())
->middleware('web')
@ -57,7 +57,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/blog.php'));
//
// Domain: api.gtoria.net
// Domain: api.virtubrick.net
//
Route::domain('api.' . DomainHelper::TopLevelDomain())
->middleware('api')
@ -65,7 +65,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/api.php'));
//
// Domain: cdn.gtoria.net
// Domain: cdn.virtubrick.net
//
Route::domain('cdn.' . DomainHelper::TopLevelDomain())
->middleware('api')
@ -73,7 +73,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/cdn.php'));
//
// Domain: setup.gtoria.net
// Domain: setup.virtubrick.net
//
Route::domain('setup.' . DomainHelper::TopLevelDomain())
->middleware('api')

View File

@ -50,8 +50,8 @@ class AppDeploymentFilenameRule implements Rule
{
array_push($files, ...[
'playerpdb.zip',
'graphictoria.zip',
'graphictoriaplayerlauncher.exe'
'virtubrick.zip',
'virtubrickplayerlauncher.exe'
]);
}
elseif($this->appType == 'studio')
@ -61,8 +61,8 @@ class AppDeploymentFilenameRule implements Rule
'imageformats.zip',
'content-scripts.zip',
'studiopdb.zip',
'graphictoriastudio.zip',
'graphictoriastudiolauncherbeta.exe'
'virtubrickstudio.zip',
'virtubrickstudiolauncherbeta.exe'
]);
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\View\Components\Admin;
use Illuminate\View\Component;
class UserSearchInput extends Component
{
/**
* Create a new component instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return view('components.admin.user-search-input');
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class UserCircle extends Component
{
/**
* Create a new component instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return view('components.user-circle');
}
}

View File

@ -6,6 +6,7 @@
"license": "MIT",
"require": {
"php": "^8.0.2",
"claviska/simpleimage": "^3.7",
"elhebert/laravel-sri": "^3.1",
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^9.2",

109
web/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "01ebc87de69ddff55214f2b48dae78c1",
"content-hash": "add8af8f80cfe2dbb0306929490c1386",
"packages": [
{
"name": "brick/math",
@ -66,6 +66,55 @@
],
"time": "2021-08-15T20:50:18+00:00"
},
{
"name": "claviska/simpleimage",
"version": "3.7.2",
"source": {
"type": "git",
"url": "https://github.com/claviska/SimpleImage.git",
"reference": "82dbef988e356baa5d73993a1351bcb6c0959269"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/claviska/SimpleImage/zipball/82dbef988e356baa5d73993a1351bcb6c0959269",
"reference": "82dbef988e356baa5d73993a1351bcb6c0959269",
"shasum": ""
},
"require": {
"ext-gd": "*",
"league/color-extractor": "0.3.*",
"php": ">=5.6.0"
},
"type": "library",
"autoload": {
"psr-0": {
"claviska": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Cory LaViska",
"homepage": "http://www.abeautifulsite.net/",
"role": "Developer"
}
],
"description": "A PHP class that makes working with images as simple as possible.",
"support": {
"issues": "https://github.com/claviska/SimpleImage/issues",
"source": "https://github.com/claviska/SimpleImage/tree/3.7.2"
},
"funding": [
{
"url": "https://github.com/claviska",
"type": "github"
}
],
"time": "2022-12-12T14:31:53+00:00"
},
{
"name": "dflydev/dot-access-data",
"version": "v3.0.1",
@ -1324,6 +1373,64 @@
},
"time": "2022-03-23T12:38:24+00:00"
},
{
"name": "league/color-extractor",
"version": "0.3.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/color-extractor.git",
"reference": "837086ec60f50c84c611c613963e4ad2e2aec806"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/color-extractor/zipball/837086ec60f50c84c611c613963e4ad2e2aec806",
"reference": "837086ec60f50c84c611c613963e4ad2e2aec806",
"shasum": ""
},
"require": {
"ext-gd": "*",
"php": ">=5.4.0"
},
"replace": {
"matthecat/colorextractor": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2",
"phpunit/phpunit": "~5"
},
"type": "library",
"autoload": {
"psr-4": {
"": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mathieu Lechat",
"email": "math.lechat@gmail.com",
"homepage": "http://matthecat.com",
"role": "Developer"
}
],
"description": "Extract colors from an image as a human would do.",
"homepage": "https://github.com/thephpleague/color-extractor",
"keywords": [
"color",
"extract",
"human",
"image",
"palette"
],
"support": {
"issues": "https://github.com/thephpleague/color-extractor/issues",
"source": "https://github.com/thephpleague/color-extractor/tree/master"
},
"time": "2016-12-15T09:30:02+00:00"
},
{
"name": "league/commonmark",
"version": "2.3.0",

View File

@ -15,7 +15,7 @@ return [
|
*/
'name' => env('APP_NAME', 'Graphictoria'),
'name' => env('APP_NAME', 'VirtuBrick'),
/*
|--------------------------------------------------------------------------
@ -54,7 +54,7 @@ return [
|
*/
'url' => env('APP_URL', 'http://gtoria.net'),
'url' => env('APP_URL', 'http://virtubrick.net'),
'asset_url' => env('ASSET_URL'),
@ -212,5 +212,16 @@ return [
'aliases' => Facade::defaultAliases()->merge([
// 'ExampleClass' => App\Example\ExampleClass::class,
])->toArray(),
/*
|--------------------------------------------------------------------------
| Testing Environment Mode
|--------------------------------------------------------------------------
|
| When test environment mode is enabled, the site will display a
| banner explaining that it's not the real site.
|
*/
'testenv' => (bool) env('IS_TEST_ENVIRONMENT', true),
];

View File

@ -4,7 +4,7 @@ return [
/*
|--------------------------------------------------------------------------
| Graphictoria Arbiter Configuration
| VirtuBrick Arbiter Configuration
|--------------------------------------------------------------------------
|
| This file holds various IP configurations for the games relay/thumbnail

View File

@ -19,7 +19,7 @@ return [
'allowed_methods' => ['*'],
'allowed_origins' => ['*.gtoria.net','*.gtoria.local'],
'allowed_origins' => ['*.virtubrick.net','*.virtubrick.local'],
'allowed_origins_patterns' => [],

View File

@ -128,7 +128,7 @@ return [
'cookie' => env(
'SESSION_COOKIE',
'GTSession'
'VBSession'
),
/*

View File

@ -18,6 +18,7 @@ return new class extends Migration
$table->string('ticket');
$table->unsignedBigInteger('userId');
$table->boolean('used')->default(false);
$table->boolean('maintenanceBypass')->default(false);
$table->timestamps();
});
}

View File

@ -18,7 +18,7 @@ return new class extends Migration
$table->string('version');
$table->string('app');
$table->string('type');
$table->int('step')->default(0);
$table->integer('step')->default(0);
$table->string('error')->nullable();
$table->timestamps();
});

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('user_ips', function (Blueprint $table) {
$table->id();
$table->string('ipAddress');
$table->unsignedBigInteger('userId');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('user_ips');
}
};

View File

@ -10,7 +10,7 @@ services:
environment:
MYSQL_ROOT_PASSWORD: 'test'
volumes:
- database-data:/graphictoria
- database-data:/virtubrick
volumes:
database-data:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -114,7 +113,7 @@ class Comments extends Component {
{
this.state.error != ''
?
<div className="alert alert-danger graphictoria-alert graphictoria-error-popup m-2 mb-0">{ this.state.error }</div>
<div className="alert alert-danger virtubrick-alert virtubrick-error-popup m-2 mb-0">{ this.state.error }</div>
:
null
}
@ -140,7 +139,7 @@ class Comments extends Component {
<div className="d-flex p-2" onMouseEnter={ () => this.setState({ mouseHover: index }) } onMouseLeave={ () => this.setState({ mouseHover: -1 }) }>
<div className="me-2">
<a href={ poster.url }>
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border graphictora-feed-user-circle" />
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border virtubrick-feed-user-circle" />
</a>
</div>
<div className="flex-fill">

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -175,7 +174,7 @@ class RevertDeploymentCard extends Component {
<DeploymentCard name={ this.props.name } index={ this.props.index } removeDeployment={ this.props.removeDeployment }>
<h5 className="mb-0">Revert Deployment</h5>
<p className="text-muted">Select a previous deployment below to roll back the { this.props.index } version.</p>
<select className="form-select mt-2" id="gt-revert-deployment" disabled={ this.state.loading }>
<select className="form-select mt-2" id="vb-revert-deployment" disabled={ this.state.loading }>
<option selected>{ this.state.loading ? 'Loading...' : 'None Selected' }</option>
{
this.state.deployments.map((deployment, index) => (
@ -232,8 +231,8 @@ class PushDeploymentCard extends Component {
case 'client':
this.neededFiles = this.neededFiles.concat([
'PlayerPdb.zip',
'Graphictoria.zip',
'GraphictoriaPlayerLauncher.exe'
'VirtuBrick.zip',
'VirtuBrickPlayerLauncher.exe'
]);
break;
case 'studio':
@ -242,8 +241,8 @@ class PushDeploymentCard extends Component {
'imageformats.zip',
'content-scripts.zip',
'StudioPdb.zip',
'GraphictoriaStudio.zip',
'GraphictoriaStudioLauncherBeta.exe'
'VirtuBrickStudio.zip',
'VirtuBrickStudioLauncherBeta.exe'
]);
break;
}
@ -377,7 +376,7 @@ class PushDeploymentCard extends Component {
}
return (
<div className="graphictoria-item-card graphictoria-game-card">
<div className="virtubrick-item-card virtubrick-game-card">
<div className="card m-2" data-bs-toggle="tooltip" data-bs-placement="top" title={ file.name }>
<div className="bg-light d-flex p-3">
<i className={classNames(fileIconClasses)}></i>
@ -424,13 +423,13 @@ class PushDeploymentCard extends Component {
<h5 className="mb-0 mt-3">Optional Configuration</h5>
<p className="text-muted mb-3">Only change if you've updated the security settings on the client/rcc. Shutting down game servers will delay deployment by 10 minutes.</p>
<div className="form-check form-switch">
<input className="form-check-input" type="checkbox" role="switch" id="gt-shut-down-servers" />
<label className="form-check-label" htmlFor="gt-shut-down-servers">Shut down game servers.</label>
<input className="form-check-input" type="checkbox" role="switch" id="vb-shut-down-servers" />
<label className="form-check-label" htmlFor="vb-shut-down-servers">Shut down game servers.</label>
</div>
<label htmlFor="gt-rcc-security-key" className="form-label mt-2">Update RCC Security Key</label>
<input type="text" id="gt-rcc-security-key" className="form-control" placeholder="New RCC Security Key" onChange={ changeEvent => this.setOptions('rccAccessKey', changeEvent.target.value) } />
<label htmlFor="gt-rcc-security-key" className="form-label mt-2">Update Version Compatibility Salt</label>
<input type="text" id="gt-rcc-security-key" className="form-control" placeholder="New Version Compatibility Salt" onChange={ changeEvent => this.setOptions('versionCompatiblityFuzzyKey', changeEvent.target.value) } />
<label htmlFor="vb-rcc-security-key" className="form-label mt-2">Update RCC Security Key</label>
<input type="text" id="vb-rcc-security-key" className="form-control" placeholder="New RCC Security Key" onChange={ changeEvent => this.setOptions('rccAccessKey', changeEvent.target.value) } />
<label htmlFor="vb-rcc-security-key" className="form-label mt-2">Update Version Compatibility Salt</label>
<input type="text" id="vb-rcc-security-key" className="form-control" placeholder="New Version Compatibility Salt" onChange={ changeEvent => this.setOptions('versionCompatiblityFuzzyKey', changeEvent.target.value) } />
</>
:
null
@ -592,10 +591,10 @@ class Deployer extends Component {
<h5>Deployment Options</h5>
<div className="d-block">
<div className="btn-group mb-1">
<input type="radio" className="btn-check" name="gt-deployment-type" id="gt-deployment-deploy" autoComplete="off" onChange={ (e)=>this.trySetDeployType(e, 'deploy') } checked={ this.state.deployType == 'deploy' } />
<label className="btn btn-sm btn-outline-primary" htmlFor="gt-deployment-deploy">Deploy</label>
<input type="radio" className="btn-check" name="gt-deployment-type" id="gt-deployment-revert" autoComplete="off" onChange={ (e)=>this.trySetDeployType(e, 'revert') } checked={ this.state.deployType == 'revert' } />
<label className="btn btn-sm btn-outline-primary" htmlFor="gt-deployment-revert">Revert</label>
<input type="radio" className="btn-check" name="vb-deployment-type" id="vb-deployment-deploy" autoComplete="off" onChange={ (e)=>this.trySetDeployType(e, 'deploy') } checked={ this.state.deployType == 'deploy' } />
<label className="btn btn-sm btn-outline-primary" htmlFor="vb-deployment-deploy">Deploy</label>
<input type="radio" className="btn-check" name="vb-deployment-type" id="vb-deployment-revert" autoComplete="off" onChange={ (e)=>this.trySetDeployType(e, 'revert') } checked={ this.state.deployType == 'revert' } />
<label className="btn btn-sm btn-outline-primary" htmlFor="vb-deployment-revert">Revert</label>
</div>
<br />
<button className="btn btn-sm btn-success" onClick={ ()=>this.createDeployment('client') } disabled={ this.deploymentExists('client') }>Deploy Client</button>
@ -604,7 +603,7 @@ class Deployer extends Component {
<hr />
{
this.state.showTypeSwitchError ?
<div className="alert alert-danger graphictoria-alert graphictoria-error-popup">Remove your { this.state.deployType == 'deploy' ? 'deployments' : 'reversions' } to change the uploader type.</div>
<div className="alert alert-danger virtubrick-alert virtubrick-error-popup">Remove your { this.state.deployType == 'deploy' ? 'deployments' : 'reversions' } to change the uploader type.</div>
:
null
}

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -104,7 +103,7 @@ class Feed extends Component {
{
this.state.error != ''
?
<div className="alert alert-danger graphictoria-alert graphictoria-error-popup m-2 mb-0">{ this.state.error }</div>
<div className="alert alert-danger virtubrick-alert virtubrick-error-popup m-2 mb-0">{ this.state.error }</div>
:
null
}
@ -126,7 +125,7 @@ class Feed extends Component {
<div className="me-2">
<a href={ poster.url }>
{ poster.type == 'User' ?
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border graphictora-feed-user-circle" /> :
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border virtubrick-feed-user-circle" /> :
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="img-fluid" />
}
</a>

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -34,7 +33,7 @@ class GameItemCard extends Component {
render() {
return (
<a
className="graphictoria-item-card graphictoria-game-card"
className="virtubrick-item-card virtubrick-game-card"
href={ this.props.item.Url }
onMouseEnter={() => this.setState({hovered: true})}
onMouseLeave={() => this.setState({hovered: false})}
@ -47,7 +46,7 @@ class GameItemCard extends Component {
className='img-fluid'
/>
<div className="p-2">
<p>{ this.props.item.Name }</p>
<p className="text-truncate">{ this.props.item.Name }</p>
<p className="text-muted small">{commaSeparate(this.props.item.Playing)} Playing</p>
<div className="d-flex mt-1">
<i className={classNames({
@ -58,7 +57,7 @@ class GameItemCard extends Component {
<div className={classNames({
'my-auto': true,
'mx-1': true,
'graphictoria-vote-bar': true,
'virtubrick-vote-bar': true,
'rounded-1': true,
'border': true,
'border-light': true,
@ -85,7 +84,7 @@ class GameItemCard extends Component {
</span>
{
this.state.hovered ?
<span className="graphictoria-item-details">
<span className="virtubrick-item-details">
<div className="card px-2">
<hr className="m-0" />
<p className="text-truncate my-1">
@ -157,7 +156,7 @@ class Games extends Component {
}
{
!this.state.pageLoaded ?
<div className="graphictoria-shop-overlay">
<div className="virtubrick-shop-overlay">
<Loader />
</div>
:
@ -181,7 +180,7 @@ class Games extends Component {
<li className="list-inline-item">
<button className="btn btn-secondary" disabled={(this.state.pageNumber <= 1) ? true : null}><i className="fa-solid fa-angle-left"></i></button>
</li>
<li className="list-inline-item graphictoria-paginator">
<li className="list-inline-item virtubrick-paginator">
<span>Page&nbsp;</span>
<input type="text" value={ this.state.pageNumber || '' } className="form-control" disabled={this.state.pageLoaded ? null : true} />
<span>&nbsp;of { this.state.pageCount || '???' }</span>

View File

@ -1,11 +1,10 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
const Loader = () => {
return (
<div className="gtoria-loader"><div></div><div></div><div></div><div></div></div>
<div className="vbrick-loader"><div></div><div></div><div></div><div></div></div>
);
};

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -15,7 +14,7 @@ import SearchBar from './SearchBar';
axios.defaults.withCredentials = true;
const searchBarId = 'graphictoria-nav-searchbar';
const searchBarId = 'virtubrick-nav-searchbar';
$(document).ready(function() {
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -14,7 +13,7 @@ import Loader from './Loader';
axios.defaults.withCredentials = true;
const playerProtocol = 'graphictoria-player';
const playerProtocol = 'virtubrick-player';
class PlaceLoadingModal extends Component {
constructor(props) {
@ -70,14 +69,14 @@ class PlaceLoadingModal extends Component {
{
this.state.showDownloadScreen ?
<>
<h5>Download Graphictoria</h5>
<p>Download Graphictoria to get access to thousands of community-driven games.</p>
<a href={ buildGenericApiUrl('setup', 'GraphictoriaPlayerLauncher.exe') } target="_blank" className="btn btn-success mt-3">Download</a>
<h5>Download VirtuBrick</h5>
<p>Download VirtuBrick to get access to thousands of community-driven games.</p>
<a href={ buildGenericApiUrl('setup', 'VirtuBrickPlayerLauncher.exe') } target="_blank" className="btn btn-success mt-3">Download</a>
</>
:
<>
<Loader />
<p>Starting Graphictoria</p>
<p>Starting VirtuBrick</p>
</>
}
</div>
@ -118,7 +117,7 @@ class PlaceLoadingErrorModal extends Component {
<div className="modal-content text-center">
<div className="modal-body d-flex flex-column pb-4">
<button type="button" className="ms-auto btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<h5>An error occurred while starting Graphictoria.</h5>
<h5>An error occurred while starting VirtuBrick.</h5>
<p>Error Detail: { this.props.message }</p>
</div>
</div>
@ -167,7 +166,7 @@ class PlaceButtons extends Component {
let protocol = playerProtocol;
let domainSplit = getCurrentDomain().split('.');
if(getCurrentDomain() == 'gtoria.local')
if(getCurrentDomain() == 'virtubrick.local')
{
protocol += '-dev';
}
@ -187,7 +186,7 @@ class PlaceButtons extends Component {
.catch(function(error) {
this.setModal(<PlaceLoadingErrorModal setModal={ this.setModal } message={ error.message } />);
//alert('Error while starting Graphictoria: ' + error.message);
//alert('Error while starting VirtuBrick: ' + error.message);
}.bind(this));
}

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -7,7 +6,7 @@ import { createRef, Component } from 'react';
import classNames from 'classnames/bind';
const itemId = 'gt-item';
const itemId = 'vb-item';
class PurchaseConfirmationModal extends Component {
constructor(props) {
@ -54,7 +53,7 @@ class PurchaseConfirmationModal extends Component {
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div className="modal-body d-flex flex-column">
<p>Would you like to purchase the { this.state.assetType } <strong>{ this.state.assetName }</strong> from { this.state.assetCreator } for <span className="graphictoria-tokens">{ this.state.assetPrice }</span>?</p>
<p>Would you like to purchase the { this.state.assetType } <strong>{ this.state.assetName }</strong> from { this.state.assetCreator } for <span className="virtubrick-tokens">{ this.state.assetPrice }</span>?</p>
<img src="/images/testing/hat.png" width="240" height="240" alt={ this.state.assetName } className="mx-auto my-2 img-fluid" />
</div>
<div className="modal-footer flex-column">
@ -63,7 +62,7 @@ class PurchaseConfirmationModal extends Component {
&nbsp;
<button className="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
</div>
<p className="text-muted pt-1">You will have <span className="graphictoria-tokens">{ Math.max(0, (this.state.userTokens - this.state.assetPrice)) }</span> after this purchase.</p>
<p className="text-muted pt-1">You will have <span className="virtubrick-tokens">{ Math.max(0, (this.state.userTokens - this.state.assetPrice)) }</span> after this purchase.</p>
</div>
</div>
</div>
@ -114,7 +113,7 @@ class NotEnoughTokensModal extends Component {
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div className="modal-body">
<p>You need <span className="graphictoria-tokens">{ this.state.assetPrice - this.state.userTokens }</span> more to purchase this item.</p>
<p>You need <span className="virtubrick-tokens">{ this.state.assetPrice - this.state.userTokens }</span> more to purchase this item.</p>
</div>
<div className="modal-footer">
<button className="btn btn-secondary" data-bs-dismiss="modal">Ok</button>

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -69,16 +68,16 @@ const SearchBar = () => {
return (
<>
<input type="text" ref={inputRef} className="form-control d-lg-flex" placeholder="Search" aria-label="Search" aria-describedby="graphictoria-nav-search-button" onChange={ changeEvent => setSearchQuery(changeEvent.target.value) } value={ searchQuery }/>
<input type="text" ref={inputRef} className="form-control d-lg-flex" placeholder="Search" aria-label="Search" aria-describedby="virtubrick-nav-search-button" onChange={ changeEvent => setSearchQuery(changeEvent.target.value) } value={ searchQuery }/>
{
searchQuery.length !== 0 ?
<div ref={dropdownRef} id="graphictoria-search-dropdown">
<ul className="dropdown-menu show" area-labelledby="graphictoria-search-dropdown">
<div ref={dropdownRef} id="virtubrick-search-dropdown">
<ul className="dropdown-menu show" area-labelledby="virtubrick-search-dropdown">
{
dropdownLinks.map(({ area, urlbase }, index) =>
<li key={index}>
<a className="dropdown-item py-2" onClick={ () => setSearchQuery('') } href={ urlbase + encodeURIComponent(searchQuery) }>Search <b className="text-truncate graphictoria-search-dropdown-truncate">{searchQuery}</b> in {area}</a>
<a className="dropdown-item py-2" onClick={ () => setSearchQuery('') } href={ urlbase + encodeURIComponent(searchQuery) }>Search <b className="text-truncate virtubrick-search-dropdown-truncate">{searchQuery}</b> in {area}</a>
</li>
)
}

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -176,14 +175,14 @@ class ShopCategories extends Component {
render() {
return (
<div className="graphictoria-shop-categories">
<div className="virtubrick-shop-categories">
<h5>Category</h5>
<ShopCategoryButton id="all" label="All Items" getCategoryAssetTypeByLabel={this.props.getCategoryAssetTypeByLabel} getCategoryAssetTypeIds={this.props.getCategoryAssetTypeIds} navigateCategory={this.props.navigateCategory} shopState={this.props.shopState} />
<ul className="list-unstyled ps-0">
{
Object.keys(shopCategories).map((categoryName, index) =>
<li className="mb-1">
<a className="text-decoration-none fw-normal align-items-center graphictoria-list-dropdown" data-bs-toggle="collapse" data-bs-target={`#${makeCategoryId(categoryName, 'collapse')}`} aria-expanded={(index === 0 ? 'true' : 'false')} href="#">{ categoryName }</a>
<a className="text-decoration-none fw-normal align-items-center virtubrick-list-dropdown" data-bs-toggle="collapse" data-bs-target={`#${makeCategoryId(categoryName, 'collapse')}`} aria-expanded={(index === 0 ? 'true' : 'false')} href="#">{ categoryName }</a>
<div className={classNames({'collapse': true, 'show': (index === 0)})} id={makeCategoryId(categoryName, 'collapse')}>
<ul className="btn-toggle-nav list-unstyled fw-normal small">
<li><ShopCategoryButton id={makeCategoryId(`all-${categoryName}`, 'type')} label={`All ${categoryName}`} categoryName={categoryName} getCategoryAssetTypeByLabel={this.props.getCategoryAssetTypeByLabel} getCategoryAssetTypeIds={this.props.getCategoryAssetTypeIds} navigateCategory={this.props.navigateCategory} shopState={this.props.shopState} /></li>
@ -216,7 +215,7 @@ class ShopItemCard extends Component {
return (
<a
className="graphictoria-item-card"
className="virtubrick-item-card"
href={ item.Url }
onMouseEnter={() => this.setState({hovered: true})}
onMouseLeave={() => this.setState({hovered: false})}
@ -231,14 +230,14 @@ class ShopItemCard extends Component {
<div className="p-2">
<p>{ item.Name }</p>
{ item.OnSale ?
<p className="graphictoria-tokens text-truncate">{commaSeparate(item.Price)}</p>
<p className="virtubrick-tokens text-truncate">{commaSeparate(item.Price)}</p>
: <p className="text-muted">Offsale</p>
}
</div>
</span>
{
this.state.hovered ?
<span className="graphictoria-item-details">
<span className="virtubrick-item-details">
<div className="card px-2">
<p className="text-truncate">
<span className="text-muted">Creator: </span><a href={ item.Creator.Url } className="text-decoration-none fw-normal">{ item.Creator.Name }</a>
@ -364,7 +363,7 @@ class Shop extends Component {
}
{
!this.state.pageLoaded ?
<div className="graphictoria-shop-overlay">
<div className="virtubrick-shop-overlay">
<Loader />
</div>
:
@ -389,7 +388,7 @@ class Shop extends Component {
<li className="list-inline-item">
<button className="btn btn-secondary" disabled={(this.state.pageNumber <= 1) ? true : null}><i className="fa-solid fa-angle-left"></i></button>
</li>
<li className="list-inline-item graphictoria-paginator">
<li className="list-inline-item virtubrick-paginator">
<span>Page&nbsp;</span>
<input type="text" value={ this.state.pageNumber || '' } className="form-control" disabled={this.state.pageLoaded ? null : true} />
<span>&nbsp;of { this.state.pageCount || '???' }</span>

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -51,6 +50,7 @@ const Scene = ({json}) => {
camera.position.set(thumbnailCameraPosition.x, thumbnailCameraPosition.y, thumbnailCameraPosition.z);
camera.lookAt(pointToLookat);
camera.translateZ(0.5);
// lighting
// FIXME: XlXi: if you toggle 3d on and off it'll create these twice
@ -119,7 +119,7 @@ class ThumbnailTool extends Component {
this.setState({ initialLoading: false });
if(this.renderable3d && localStorage.getItem('gt-use-3d-thumbnails') === 'true')
if(this.renderable3d && localStorage.getItem('vb-use-3d-thumbnails') === 'true')
this.toggle3D();
}
}
@ -169,7 +169,7 @@ class ThumbnailTool extends Component {
let is3d = !this.state.is3d;
this.setState({ loading: true, is3d: is3d, seed3d: Math.random() });
localStorage.setItem('gt-use-3d-thumbnails', is3d);
localStorage.setItem('vb-use-3d-thumbnails', is3d);
if(is3d) {
this.loadThumbnail(`thumbnails/v1/asset?id=${this.assetId}&type=3D`, true);

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -10,7 +9,7 @@ import { render } from 'react-dom';
import Deployer from '../components/Deployer';
const deployerId = 'gt-deployer';
const deployerId = 'vb-deployer';
$(document).ready(function() {
if (document.getElementById(deployerId)) {

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -7,8 +6,8 @@ import $ from 'jquery';
import * as Bootstrap from 'bootstrap';
import React from 'react';
const navId = 'gt-blog-nav';
const hideClass = 'graphictoria-blognav-hide';
const navId = 'vb-blog-nav';
const hideClass = 'virtubrick-blognav-hide';
function scrollChanged() {
const nav = document.getElementById(navId);

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -10,7 +9,7 @@ import { render } from 'react-dom';
import Feed from '../components/Feed';
const feedId = 'gt-dash-feed';
const feedId = 'vb-dash-feed';
$(document).ready(function() {
if (document.getElementById(feedId)) {

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -10,7 +9,7 @@ import { render } from 'react-dom';
import Games from '../components/Games';
const gamesId = 'gt-games-main';
const gamesId = 'vb-games-main';
$(document).ready(function() {
if (document.getElementById(gamesId)) {

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -12,9 +11,9 @@ import Comments from '../components/Comments';
import PurchaseButton from '../components/PurchaseButton';
import ThumbnailTool from '../components/ThumbnailTool';
const purchaseId = 'gt-purchase-button';
const commentsId = 'gt-comments';
const thumbnailId = 'gt-thumbnail';
const purchaseId = 'vb-purchase-button';
const commentsId = 'vb-comments';
const thumbnailId = 'vb-thumbnail';
$(document).ready(function() {
if (document.getElementById(commentsId)) {

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -22,7 +21,7 @@ const randomEuler = () => [Math.random() * Math.PI, Math.random() * Math.PI, Mat
const randomData = Array.from({ length: 2000 }, (r = 200) => ({ random: Math.random(), position: randomVector(r), rotation: randomEuler() }));
function Scene() {
const { nodes, materials } = useGLTF('/models/graphictoriapart.glb');
const { nodes, materials } = useGLTF('/models/virtubrickpart.glb');
return (
<>
@ -71,8 +70,8 @@ function Camera({ ...props }){
let ButtonHistory = []
function attemptBypass() {
axios.post(buildGenericApiUrl('apis', 'v1/maintenance/bypass'), {
'password': $('#gt_mt_buttons > input').val(),
axios.post(buildGenericApiUrl('api', 'maintenance/v1/bypass'), {
'password': $('#vbrick_mt_buttons > input').val(),
'buttons': ButtonHistory.slice(-40)
})
.then((response) => {
@ -87,11 +86,11 @@ $(document).ready(function() {
<Scene />
</Suspense>
</Canvas>),
document.getElementsByClassName('gtoria-maintenance-background')[0]
document.getElementsByClassName('vbrick-maintenance-background')[0]
);
$('#gt_mt_buttons').on('click', 'button', function() {
let ButtonId = parseInt(this.getAttribute('name').substr(8)); //gt_mtbtnX
$('#vbrick_mt_buttons').on('click', 'button', function() {
let ButtonId = parseInt(this.getAttribute('name').substr(8)); //vb_mtbtnX
ButtonHistory.push(ButtonId);
attemptBypass();

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -12,9 +11,9 @@ import Comments from '../components/Comments';
import ThumbnailTool from '../components/ThumbnailTool';
import PlaceButtons from '../components/PlaceButtons';
const thumbnailId = 'gt-thumbnail';
const buttonsId = 'gt-place-buttons';
const commentsId = 'gt-comments';
const thumbnailId = 'vb-thumbnail';
const buttonsId = 'vb-place-buttons';
const commentsId = 'vb-comments';
$(document).ready(function() {
if (document.getElementById(thumbnailId)) {

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
@ -10,7 +9,7 @@ import { render } from 'react-dom';
import Shop from '../components/Shop';
const shopId = 'gt-shop-main';
const shopId = 'vb-shop-main';
$(document).ready(function() {
if (document.getElementById(shopId)) {

View File

@ -1,11 +1,10 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/
import $ from 'jquery';
const configId = 'gt-config-values';
const configId = 'vb-config-values';
$(document).ready(function() {
if (document.getElementById(configId)) {

View File

@ -1,5 +1,4 @@
/*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022
*/

View File

@ -0,0 +1,45 @@
// XlXi: Loads bootstrap without utilities/api.
// scss-docs-start import-stack
// Configuration
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins";
@import "~bootstrap/scss/utilities";
// Layout & components
@import "~bootstrap/scss/root";
@import "~bootstrap/scss/reboot";
@import "~bootstrap/scss/type";
@import "~bootstrap/scss/images";
@import "~bootstrap/scss/containers";
@import "~bootstrap/scss/grid";
@import "~bootstrap/scss/tables";
@import "~bootstrap/scss/forms";
@import "~bootstrap/scss/buttons";
@import "~bootstrap/scss/transitions";
@import "~bootstrap/scss/dropdown";
@import "~bootstrap/scss/button-group";
@import "~bootstrap/scss/nav";
@import "~bootstrap/scss/navbar";
@import "~bootstrap/scss/card";
@import "~bootstrap/scss/accordion";
@import "~bootstrap/scss/breadcrumb";
@import "~bootstrap/scss/pagination";
@import "~bootstrap/scss/badge";
@import "~bootstrap/scss/alert";
@import "~bootstrap/scss/progress";
@import "~bootstrap/scss/list-group";
@import "~bootstrap/scss/close";
@import "~bootstrap/scss/toasts";
@import "~bootstrap/scss/modal";
@import "~bootstrap/scss/tooltip";
@import "~bootstrap/scss/popover";
@import "~bootstrap/scss/carousel";
@import "~bootstrap/scss/spinners";
@import "~bootstrap/scss/offcanvas";
@import "~bootstrap/scss/placeholders";
// Helpers
@import "~bootstrap/scss/helpers";
// scss-docs-end import-stack

View File

@ -1,5 +1,4 @@
// © XlXi 2021
// Graphictoria 5
@function tint-color($color, $percent){
@return mix(white, $color, $percent);
@ -12,7 +11,7 @@
// Lumen 5.0.1
// Bootswatch
$theme: "graphictoria" !default;
$theme: "virtubrick" !default;
//
// Color system
@ -30,19 +29,20 @@ $gray-800: #333 !default;
$gray-900: #222 !default;
$black: #000 !default;
$gtblue: #348aff !default;
$blue: #158cba !default;
$indigo: #6610f2 !default;
$purple: #6f42c1 !default;
$pink: #e83e8c !default;
$red: #ff4136 !default;
$orange: #fd7e14 !default;
$yellow: #ff851b !default;
$green: #28b62c !default;
$teal: #20c997 !default;
$cyan: #75caeb !default;
$gtblue: #348aff !default;
$blue: #158cba !default;
$indigo: #6610f2 !default;
$purple: #6f42c1 !default;
$pink: #e83e8c !default;
$red: #ff4136 !default;
$orange: #fd7e14 !default;
$yellow: #ff851b !default;
$realyellow: #ffde1b !default;
$green: #28b62c !default;
$teal: #20c997 !default;
$cyan: #75caeb !default;
$graphictoria: $gtblue !default;
$virtubrick: $gtblue !default;
$primary: $blue !default;
$secondary: $gray-200 !default;
$success: $green !default;

View File

@ -1,13 +1,10 @@
// © XlXi 2021
// Graphictoria 5
@use "sass:math";
// Lumen 5.0.1
// Bootswatch
@import "Variables";
@import "~bootstrap/scss/bootstrap";
@import "./scss/fontawesome.scss";
@import "./scss/brands.scss";
@import "./scss/duotone.scss";
@ -16,6 +13,14 @@
@import "./scss/solid.scss";
@import "./scss/thin.scss";
@import "Variables";
@import "Bootstrap";
// XlXi: Edit utilities API.
// Border is removed because of how stupidly it's handled by Bootstrap. It completely breaks our dark theme.
$utilities: map-remove($utilities, "border", "border-top", "border-end", "border-bottom", "border-start");
@import "~bootstrap/scss/utilities/api";
// Variables
$web-font-path: "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,300;0,400;0,700;1,400&display=swap" !default;
@ -40,7 +45,7 @@ img.twemoji {
// Shop
.graphictoria-tokens {
.virtubrick-tokens {
background: 0 1px/contain no-repeat url("/images/symbols/token.svg");
color: #e59800!important;
font-weight: bold;
@ -72,22 +77,22 @@ img.twemoji {
}
}
.graphictoria-asset-thumbnail {
.virtubrick-asset-thumbnail {
width: 420px;
height: 420px;
}
.graphictoria-game-thumbnail {
.virtubrick-game-thumbnail {
width: 640px;
height: 360px;
}
.graphictoria-smaller-page {
.virtubrick-smaller-page {
max-width: 1096px;
margin: 0 auto 0 auto;
}
.graphictoria-list-dropdown::after {
.virtubrick-list-dropdown::after {
@include caret-down();
content: "";
@ -96,7 +101,7 @@ img.twemoji {
vertical-align: 0.255em;
}
.graphictoria-item-card {
.virtubrick-item-card {
text-decoration: none!important;
font-weight: 400!important;
display: inline-block;
@ -124,7 +129,7 @@ img.twemoji {
color: inherit!important;
}
.graphictoria-item-details {
.virtubrick-item-details {
position: relative;
display: flex;
@ -144,12 +149,12 @@ img.twemoji {
}
}
.graphictoria-item-card > span > img {
.virtubrick-item-card > span > img {
background: url("/Images/Item-Image-Vignette.png");
background-size: cover;
}
.graphictoria-game-card {
.virtubrick-game-card {
@media (max-width: 576px) {
width: math.div(100%, 2)
}
@ -171,7 +176,7 @@ img.twemoji {
}
}
.graphictoria-shop-overlay {
.virtubrick-shop-overlay {
position: absolute;
width: 100%;
height: 100%;
@ -182,19 +187,19 @@ img.twemoji {
z-index: 10;
}
.graphictoria-shop-overlay > .gtoria-loader {
.virtubrick-shop-overlay > .vbrick-loader {
margin: auto;
}
.graphictoria-shop-categories {
.virtubrick-shop-categories {
border: 0;
@media (min-width: 768px) {
html.gtoria-light & {
html.vbrick-light & {
border-right: 2px solid #dee2e6!important;
}
html.gtoria-dark & {
html.vbrick-dark & {
border-right: 2px solid #333!important;
}
@ -206,19 +211,19 @@ img.twemoji {
// Maintenance
.gtoria-maintenance-background {
.vbrick-maintenance-background {
position: absolute;
width: 100%;
height: 100%;
z-index: -9999;
}
.gtoria-maintenance-form {
html.gtoria-light & {
.vbrick-maintenance-form {
html.vbrick-light & {
background: radial-gradient($gray-100 5%, transparent 65%);
}
html.gtoria-dark & {
html.vbrick-dark & {
background: radial-gradient(shade-color($gray-900, 30%) 5%, transparent 65%);
}
@ -242,7 +247,7 @@ img.twemoji {
}
.modal-content {
html.gtoria-dark & {
html.vbrick-dark & {
background-color: #222 !important;
}
}
@ -257,11 +262,11 @@ img.twemoji {
// Loader
.gtoria-loader-center {
.vbrick-loader-center {
margin: auto;
}
.gtoria-loader {
.vbrick-loader {
display: inline-block;
position: relative;
margin: auto auto 0 auto;
@ -269,43 +274,43 @@ img.twemoji {
height: 80px;
}
.gtoria-loader div {
.vbrick-loader div {
position: absolute;
top: 33px;
width: 13px;
height: 13px;
border-radius: 50%;
html.gtoria-light & {
html.vbrick-light & {
background-color: $dark;
}
html.gtoria-dark & {
html.vbrick-dark & {
background-color: $light;
}
}
.gtoria-loader div:nth-child(1) {
.vbrick-loader div:nth-child(1) {
left: 8px;
animation: gtoria-ld-p1 0.5s infinite;
animation: vbrick-ld-p1 0.5s infinite;
}
.gtoria-loader div:nth-child(2) {
.vbrick-loader div:nth-child(2) {
left: 8px;
animation: gtoria-ld-p2 0.5s infinite;
animation: vbrick-ld-p2 0.5s infinite;
}
.gtoria-loader div:nth-child(3) {
.vbrick-loader div:nth-child(3) {
left: 32px;
animation: gtoria-ld-p2 0.5s infinite;
animation: vbrick-ld-p2 0.5s infinite;
}
.gtoria-loader div:nth-child(4) {
.vbrick-loader div:nth-child(4) {
left: 56px;
animation: gtoria-ld-p3 0.5s infinite;
animation: vbrick-ld-p3 0.5s infinite;
}
@keyframes gtoria-ld-p1 {
@keyframes vbrick-ld-p1 {
0% {
transform: scale(0);
}
@ -314,7 +319,7 @@ img.twemoji {
}
}
@keyframes gtoria-ld-p3 {
@keyframes vbrick-ld-p3 {
0% {
transform: scale(1);
}
@ -323,7 +328,7 @@ img.twemoji {
}
}
@keyframes gtoria-ld-p2 {
@keyframes vbrick-ld-p2 {
0% {
transform: translate(0, 0);
}
@ -334,31 +339,31 @@ img.twemoji {
// Background
html, body, #gtoria-root {
html, body, #vbrick-root {
height: 100%;
background: transparent;
color: inherit;
}
html {
&.gtoria-light {
&.vbrick-light {
background-color: $gray-100;
color: $gray-900;
}
&.gtoria-dark {
&.vbrick-dark {
background-color: shade-color($gray-900, 30%);
color: $gray-100;
}
}
#gtoria-root {
#vbrick-root {
display: flex;
flex-direction: column;
height: 100%;
}
.graphictoria-home {
.virtubrick-home {
background-image: url("/Images/Backgrounds/Home.png");
background-size: cover;
background-repeat: no-repeat;
@ -367,7 +372,7 @@ html {
display: flex;
}
.graphictoria-home-about {
.virtubrick-home-about {
background-image: url("/Images/Backgrounds/About.png");
background-size: cover;
background-repeat: no-repeat;
@ -375,7 +380,7 @@ html {
min-height: 500px;
}
.graphictoria-home-about-card {
.virtubrick-home-about-card {
color: #fff;
background: #000000ad;
border-radius: 5px;
@ -385,21 +390,21 @@ html {
border-width: 0 0 2px;
}
.graphictoria-nojs {
.virtubrick-nojs {
background-image: url("/Images/Backgrounds/NoJs.png");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.graphictoria-admin {
.virtubrick-admin {
background-image: url("/Images/Backgrounds/stars.jpg");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.graphictoria-blog {
.virtubrick-blog {
/* XlXi: I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS */
background-image: url("/Images/Backgrounds/Blog.png")!important;
background-size: cover!important;
@ -411,27 +416,27 @@ html {
// Home Page
.graphictoria-homepage-header {
.virtubrick-homepage-header {
font-size: 4rem;
font-weight: bold;
}
.graphictoria-homepage-fine-print {
.virtubrick-homepage-fine-print {
font-size: .6rem;
opacity: 70%;
}
.graphictoria-small-aligned-text {
.virtubrick-small-aligned-text {
font-size: .6rem;
vertical-align: middle;
}
.graphictoria-home-shadow {
.virtubrick-home-shadow {
text-shadow: 0 0 4px $gray-700;
}
// Character
.gt-charimg {
.vb-charimg {
max-height: 300px;
max-width: 300px;
@media (max-width: 768px) {
@ -440,13 +445,13 @@ html {
}
}
.graphictora-user-circle {
.virtubrick-user-circle {
border-radius: 50%;
background: url("/Images/User-Image-Vignette.png");
background-size: cover;
}
.graphictora-feed-user-circle {
.virtubrick-feed-user-circle {
border-radius: 50%;
background: url("/Images/User-Image-Vignette.png");
background-size: cover;
@ -457,11 +462,75 @@ html {
// Border
.border {
html.gtoria-dark & {
border-color: $gray-700!important;
html.vbrick-dark & {
border: 1px solid $gray-700;
}
html.gtoria-light & {
border-color: $border-color!important;
html.vbrick-light & {
border: 1px solid $border-color;
}
&-top {
html.vbrick-dark & {
border-top: $gray-700;
}
html.vbrick-light & {
border-top: $border-color;
}
}
&-end {
html.vbrick-dark & {
border-right: $gray-700;
}
html.vbrick-light & {
border-right: $border-color;
}
}
&-bottom {
html.vbrick-dark & {
border-bottom: $gray-700;
}
html.vbrick-light & {
border-bottom: $border-color;
}
}
&-start {
html.vbrick-dark & {
border-left: $gray-700;
}
html.vbrick-light & {
border-left: $border-color;
}
}
&-top-0 {
border-top: 0!important;
}
&-end-0 {
border-end: 0!important;
}
&-bottom-0 {
border-bottom: 0!important;
}
&-start-0 {
border-start: 0!important;
}
&-vb-online-website {
border-color: #22acff!important;
}
&-vb-in-game {
border-color: #00d926!important;
}
&-vb-in-studio {
border-color: #ff8f00!important;
}
}
@ -477,11 +546,11 @@ html {
}
}
.bg-graphictoria {
background-color: $graphictoria;
.bg-virtubrick {
background-color: $virtubrick;
}
.graphictoria-navbar {
.virtubrick-navbar {
background-color: $white;
border-color: shade-color($white, 10%);
border-style: solid;
@ -490,7 +559,7 @@ html {
padding-top: 4px;
padding-bottom: 4px;
html.gtoria-light & {
html.vbrick-light & {
background-color: $white;
border-color: shade-color($white, 10%);
@ -543,7 +612,7 @@ html {
}
}
html.gtoria-dark & {
html.vbrick-dark & {
background-color: $gray-900;
border-color: tint-color($gray-900, 10%);
@ -596,32 +665,32 @@ html {
}
}
.graphictoria-blognav {
.virtubrick-blognav {
transition: background 100ms, border-color 100ms;
transition-timing-function: ease-out;
}
.graphictoria-blognav-hide {
.virtubrick-blognav-hide {
background: #ffffff00!important;
border-color: #ffffff00!important;
}
.graphictoria-nav-margin {
.virtubrick-nav-margin {
margin-top: 63px;
}
.graphictoria-nav-splitter {
.virtubrick-nav-splitter {
margin-top: 16px;
margin-bottom: 16px !important;
}
.graphictoria-user-dropdown::after {
.virtubrick-user-dropdown::after {
position: absolute;
top: 50%;
right: 0;
}
.graphictoria-search, #graphictoria-search-dropdown {
.virtubrick-search, #virtubrick-search-dropdown {
position: absolute;
@media (max-width: 992px) {
display: none;
@ -636,11 +705,11 @@ html {
}
}
.graphictoria-search {
.virtubrick-search {
font-family: "FontAwesome", $font-family-sans-serif;
}
.graphictoria-search-dropdown-truncate {
.virtubrick-search-dropdown-truncate {
@media (min-width: 992px) {
max-width: 5.375rem;
}
@ -651,21 +720,21 @@ html {
margin-bottom: -0.35rem;
}
#graphictoria-search-dropdown > .dropdown-menu {
#virtubrick-search-dropdown > .dropdown-menu {
width: 100%;
left: 0;
}
// Cards
.graphictoria-small-card {
.virtubrick-small-card {
@media (min-width: 992px) {
max-width: 50%;
margin: auto;
}
}
.graphictoria-moderation-card {
.virtubrick-moderation-card {
@media (min-width: 992px) {
max-width: 70%;
margin: auto;
@ -674,7 +743,7 @@ html {
.card {
@include shadow();
html.gtoria-dark & {
html.vbrick-dark & {
background-color: #222;
}
}
@ -686,7 +755,7 @@ html {
overflow-y: auto !important;
}
.graphictoria-center-vh {
.virtubrick-center-vh {
margin-top: auto;
margin-left: auto;
margin-right: auto;
@ -731,7 +800,7 @@ html {
&-secondary {
border-color: shade-color($secondary, 10%);
html.gtoria-dark & {
html.vbrick-dark & {
color: $white;
background-color: $dark;
border-color: shade-color($dark, 10%);
@ -787,11 +856,11 @@ html {
background: transparent;
border: 0;
html.gtoria-light & {
html.vbrick-light & {
color: rgba(var(--bs-black-rgb),var(--bs-text-opacity));
}
html.gtoria-dark & {
html.vbrick-dark & {
color: rgba(var(--bs-light-rgb),var(--bs-text-opacity));
}
@ -810,11 +879,11 @@ html {
background: transparent;
border: 0;
html.gtoria-light & {
html.vbrick-light & {
color: rgba(var(--bs-black-rgb),var(--bs-text-opacity));
}
html.gtoria-dark & {
html.vbrick-dark & {
color: rgba(var(--bs-light-rgb),var(--bs-text-opacity));
}
@ -833,11 +902,11 @@ html {
background: transparent;
border: 0;
html.gtoria-light & {
html.vbrick-light & {
color: rgba(var(--bs-black-rgb),var(--bs-text-opacity));
}
html.gtoria-dark & {
html.vbrick-dark & {
color: rgba(var(--bs-light-rgb),var(--bs-text-opacity));
}
@ -876,7 +945,7 @@ html {
}
input {
html.gtoria-dark & {
html.vbrick-dark & {
background-color: $gray-800;
color: $gray-100;
border-color: $gray-700;
@ -948,13 +1017,13 @@ input {
border-top-width: 1px;
@include box-shadow(none);
html.gtoria-dark & {
html.vbrick-dark & {
color: $gray-100;
background-color: $gray-800;
border-color: $gray-700;
}
html.gtoria-light & {
html.vbrick-light & {
color: $gray-500;
background-color: $white;
border-color: $gray-400;
@ -962,7 +1031,7 @@ input {
}
.dropdown-item {
html.gtoria-dark & {
html.vbrick-dark & {
color: $gray-100;
&:not(.disabled):hover {
@ -971,7 +1040,7 @@ input {
}
}
.graphictoria-nav-dropdown {
.virtubrick-nav-dropdown {
margin-top: 11px !important;
border-top: 0;
border-radius: 0 0 0.25rem 0.25rem;
@ -1041,11 +1110,11 @@ input {
}
}
.graphictoria-paginator * {
.virtubrick-paginator * {
display: inline-block;
}
.graphictoria-paginator > input {
.virtubrick-paginator > input {
width: 35px;
text-align: center;
padding: 0;
@ -1098,6 +1167,11 @@ input {
background-color: $warning;
border-color: shade-color($warning, 10%);
}
&-yellow {
background-color: $realyellow;
border-color: shade-color($realyellow, 10%);
}
&-dark {
background-color: $dark;
@ -1125,7 +1199,7 @@ input {
}
}
.graphictoria-alert {
.virtubrick-alert {
border-radius: 0;
text-align: center;
margin-bottom: 0;
@ -1133,7 +1207,7 @@ input {
padding-bottom: 0.35rem;
}
.graphictoria-alert > .btn-close {
.virtubrick-alert > .btn-close {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
}
@ -1222,10 +1296,10 @@ a.list-group-item {
// Footer
.footer {
html.gtoria-dark & {
html.vbrick-dark & {
background-color: $gray-900 !important;
}
html.gtoria-light & {
html.vbrick-light & {
background-color: $white !important;
}
}
@ -1433,7 +1507,7 @@ p {
align-items: center !important;
}
.graphictoria-error-popup {
.virtubrick-error-popup {
margin-bottom: 10px;
border-radius: 10px;
@ -1447,12 +1521,12 @@ p {
}
// Voting
.graphictoria-vote-bar {
.virtubrick-vote-bar {
// border
html.gtoria-dark & {
html.vbrick-dark & {
border-color: $gray-700;
}
html.gtoria-light & {
html.vbrick-light & {
border-color: $border-color;
}
@ -1471,3 +1545,44 @@ p {
position: relative;
height: 10px;
}
// Tables
table {
html.vbrick-light & {
color: rgba(var(--bs-black-rgb),var(--bs-text-opacity));
}
html.vbrick-dark & {
color: rgba(var(--bs-light-rgb),var(--bs-text-opacity));
}
}
.table>:not(:first-child) {
html.vbrick-dark & {
border-top: 1px solid $gray-700;
}
html.vbrick-light & {
border-top: 1px solid $border-color;
}
}
table > tbody > tr > th {
font-weight: normal;
}
.virtubrick-table {
margin-bottom: 0;
}
.virtubrick-table > tbody > tr:last-child > th {
border: unset;
}
.virtubrick-table > thead {
html.vbrick-dark & {
background-color: #ffffff0f;
}
html.vbrick-light & {
background-color: #0000000f;
}
}

View File

@ -5,7 +5,7 @@
])
@if(Auth::check() && Auth::user()->hasRoleset($roleset))
<div class="card gt-admin-card">
<div class="card vb-admin-card">
<div class="card-header bg-{{ $color }} text-light">
{{ $name }}
</div>

View File

@ -2,7 +2,7 @@
'name'
])
<span class="gt-admin-navtitle">{{ $name }}</span>
<ul class="gt-admin-nav nav flex-column">
<span class="vb-admin-navtitle">{{ $name }}</span>
<ul class="vb-admin-nav nav flex-column">
{{ $slot }}
</ul>

View File

@ -2,7 +2,7 @@
'stat'
])
<div class="my-auto rounded-1 bg-secondary border border-light right-0 me-1 position-relative graphictoria-admin-usagebar">
<div class="my-auto rounded-1 bg-secondary border border-light right-0 me-1 position-relative virtubrick-admin-usagebar">
@php
$usage_bar_color = 'bg-primary';
$usage_bar_usage = $stat * 100;
@ -15,7 +15,7 @@
$usage_bar_color = 'bg-danger'; // Red
@endphp
<div
class="{{ $usage_bar_color }} rounded-1 position-absolute graphictoria-admin-usagebar"
class="{{ $usage_bar_color }} rounded-1 position-absolute virtubrick-admin-usagebar"
style="width:{{ $usage_bar_usage }}%!important;height:8px!important;"
></div>
</div>

View File

@ -0,0 +1,15 @@
@props([
'id',
'definition'
])
<div class="col-6">
<label for="vb-{{ $id }}-search" class="form-label">{{ $definition }}</label>
<form method="POST" action="{{ route('admin.usersearch') }}" enctype="multipart/form-data">
@csrf
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="{{ $definition }} Here" aria-label="{{ $definition }} Here" name="{{ $id }}-search" id="vb-{{ $id }}-search" aria-describedby="vb-{{ $id }}-search-btn">
<button type="submit" class="btn btn-primary" type="button" name="{{ $id }}-button" id="vb-{{ $id }}-search-btn">Search</button>
</div>
</form>
</div>

View File

@ -1,5 +1,5 @@
@php
$classes = ['card', 'graphictoria-small-card', 'shadow-sm'];
$classes = ['card', 'virtubrick-small-card', 'shadow-sm'];
if(isset($attributes['class']))
$classes = array_merge($classes, explode(' ', $attributes['class']));

View File

@ -1 +1 @@
<div class="gtoria-loader"><div></div><div></div><div></div><div></div></div>
<div class="vbrick-loader"><div></div><div></div><div></div><div></div></div>

View File

@ -0,0 +1,35 @@
@props([
'user',
'statusIndicator',
'size'
])
@php
// 37x37 Default
$size = isset($size) ? $size : 37;
$showStatus = (!isset($statusIndicator) || $statusIndicator);
$classes = [
'img-fluid',
'border',
'me-1',
'virtubrick-user-circle'
];
if($showStatus)
{
// TODO: XlXi: Advanced user presence. (in games, in studio, etc)
if($user->isOnline())
$classes = array_merge($classes, ['border-vb-online-website', 'border-2']);
}
@endphp
<span class="d-flex align-items-center">
{{-- TODO: XlXi: User headshots --}}
<img
src="{{ asset('images/testing/headshot.png') }}"
@class($classes)
width="{{ $size }}"
height="{{ $size }}"
>
<p>{{ $user->username }}</p>
</span>

View File

@ -1,6 +1,6 @@
@extends('layouts.email')
@section('title', 'Graphictoria Password Reset')
@section('title', config('app.name') . ' Password Reset')
@section('content')
<h4>Hello, <b>{{ $user }}</b>!</h4>

View File

@ -3,10 +3,10 @@
@section('title', 'Bad Request')
@section('content')
<div class="container graphictoria-center-vh">
<div class="container virtubrick-center-vh">
<x-card title="BAD REQUEST">
<x-slot name="body">
There was a problem with your request. If you believe this is an error on our part, contact us at <a href="mailto:support@gtoria.net" class="fw-bold text-decoration-none">support@gtoria.net</a>!
There was a problem with your request. If you believe this is an error on our part, contact us at <a href="mailto:support@virtubrick.net" class="fw-bold text-decoration-none">support@virtubrick.net</a>!
</x-slot>
<x-slot name="footer">
<div class="mt-2">

View File

@ -3,11 +3,11 @@
@section('title', 'Unauthorized')
@section('content')
<div class="container graphictoria-center-vh">
<div class="container virtubrick-center-vh">
<x-card title="UNAUTHORIZED">
<x-slot name="body">
You're missing the proper authentication to view this page. If you believe this is an error, contact us at <a href="mailto:support@gtoria.net" class="fw-bold text-decoration-none">support@gtoria.net</a>!
</x-slot>
You're missing the proper authentication to view this page. If you believe this is an error, contact us at <a href="mailto:support@virtubrick.net" class="fw-bold text-decoration-none">support@virtubrick.net</a>!
<x-slot name="footer">
<div class="mt-2">
<a class="btn btn-primary px-4 me-2" href="{{ url('/') }}">Home</a>

View File

@ -3,10 +3,10 @@
@section('title', 'Forbidden')
@section('content')
<div class="container graphictoria-center-vh">
<div class="container virtubrick-center-vh">
<x-card title="FORBIDDEN">
<x-slot name="body">
You don't have permission to view this page. If you believe this is an error, contact us at <a href="mailto:support@gtoria.net" class="fw-bold text-decoration-none">support@gtoria.net</a>!
You don't have permission to view this page. If you believe this is an error, contact us at <a href="mailto:support@virtubrick.net" class="fw-bold text-decoration-none">support@virtubrick.net</a>!
</x-slot>
<x-slot name="footer">
<div class="mt-2">

View File

@ -7,10 +7,10 @@ $errorTitles = ['OH NOES!!!', 'BZZT', 'ERROR', 'UH OH.'];
@section('title', 'Not Found')
@section('content')
<div class="container graphictoria-center-vh">
<div class="container virtubrick-center-vh">
<x-card title="{{ $errorTitles[array_rand($errorTitles)] }}">
<x-slot name="body">
We've looked far and wide and weren't able to find the page you were looking for. If you believe this is an error, contact us at <a href="mailto:support@gtoria.net" class="fw-bold text-decoration-none">support@gtoria.net</a>!
We've looked far and wide and weren't able to find the page you were looking for. If you believe this is an error, contact us at <a href="mailto:support@virtubrick.net" class="fw-bold text-decoration-none">support@virtubrick.net</a>!
</x-slot>
<x-slot name="footer">
<div class="mt-2">

View File

@ -3,10 +3,10 @@
@section('title', 'Internal Server Error')
@section('content')
<div class="container graphictoria-center-vh">
<div class="container virtubrick-center-vh">
<x-card title="INTERNAL SERVER ERROR">
<x-slot name="body">
Oops, we ran into an issue while trying to process your request, please try again later in a few minutes. If the issue persists after a few minutes, please contact us at <a href="mailto:support@gtoria.net" class="fw-bold text-decoration-none">support@gtoria.net</a>.
Oops, we ran into an issue while trying to process your request, please try again later in a few minutes. If the issue persists after a few minutes, please contact us at <a href="mailto:support@virtubrick.net" class="fw-bold text-decoration-none">support@virtubrick.net</a>.
</x-slot>
<x-slot name="footer">
<div class="mt-2">

View File

@ -3,7 +3,7 @@
@section('title', 'Not Implemented')
@section('content')
<div class="container graphictoria-center-vh">
<div class="container virtubrick-center-vh">
<x-card title="NOT IMPLEMENTED">
<x-slot name="body">
todo

Some files were not shown because too many files have changed in this diff Show More