Compare commits
No commits in common. "XlXi/Rewrite-2" and "main" have entirely different histories.
XlXi/Rewri
...
main
|
|
@ -3,4 +3,3 @@
|
|||
################################################################################
|
||||
|
||||
/.vs
|
||||
/web.old
|
||||
33
README.md
33
README.md
|
|
@ -1,31 +1,2 @@
|
|||
<p align="center">
|
||||
<img src="etc/readmecontent/WPLogoText.png?raw=true" alt="Virtubrick Logo With Web Platform Text" />
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## Licensing
|
||||
It is important that you understand licensing before accessing this repository; it's in plain english... You do not have permission to use, distribute, modify, or share the contents of this repository per[^1] [XlXi](mailto:wagnessgaming2014@gmail.com)'s discretion[^2].
|
||||
|
||||
[^1]: Per: For each.
|
||||
[^2]: Discretion: The freedom to decide what should be done in a particular situation.
|
||||
|
||||
---
|
||||
|
||||
## Branch Rules
|
||||
When committing a major change, it is highly suggested that you create a new branch following the naming scheme below:
|
||||
|
||||
`Username/Change`
|
||||
|
||||
Where "Username" is your name and "Change" is the major change you are making. Ex: `XlXi/Rewrite-2`.
|
||||
These branch rules allow me to merge changes using GitHub's web interface rather than Visual Studio. It's a major time saver, so just follow the branch rules.
|
||||
|
||||
---
|
||||
|
||||
## Contacts
|
||||
- [XlXi](mailto:wagnessgaming2014@gmail.com) (Owner, Primary code owner)
|
||||
|
||||
---
|
||||
|
||||
Copyright © XlXi 2023
|
||||
Virtubrick
|
||||
# Graphictoria React App
|
||||
This branch of the Graphictoria Web Platform is heavily outdated. Please see the "XlXi/Rewrite-2" branch.
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,5 +0,0 @@
|
|||
REM : XlXi 2022
|
||||
REM : Put this in the directory of your PNG export.
|
||||
REM : ImageMagick is required.
|
||||
|
||||
magick convert -delay 333,10000 -loop 0 -alpha set -dispose previous *.png ani.gif
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 977 KiB |
Binary file not shown.
|
|
@ -1,20 +0,0 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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-----
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
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-----
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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-----
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||
subjectAltName = @alt_names
|
||||
[alt_names]
|
||||
DNS.1 = localhost
|
||||
DNS.2 = virtubrick.local
|
||||
DNS.3 = *.virtubrick.local
|
||||
DNS.4 = *.*.virtubrick.local
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
-----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-----
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
-----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-----
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
-----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-----
|
||||
Binary file not shown.
|
|
@ -1,90 +0,0 @@
|
|||
# Allow read in the public directories.
|
||||
<Directory "C:/graphictoria/COMMIT_HASH/web/public/">
|
||||
Require all granted
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
<Directory "C:/graphictoria/COMMIT_HASH/web/public_api/">
|
||||
Require all granted
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
|
||||
# Disallow access to admin JS
|
||||
<Directory "C:/graphictoria/COMMIT_HASH/web/public/js/adm/">
|
||||
Require all denied
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
|
||||
# Defaults for the proceding virtualhosts on *.gtoria.net
|
||||
<VirtualHost *:80 *:443>
|
||||
ServerAdmin admin@gtoria.net
|
||||
ServerName gtoria.net
|
||||
|
||||
ServerAlias www.gtoria.net
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.crt"
|
||||
SSLCertificateKeyFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.key"
|
||||
|
||||
ErrorLog "C:/graphictoria/logs/gt-error.log"
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Host}i\" \"%{Referer}i\" \"%{User-agent}i\"" gtoria
|
||||
CustomLog "C:/graphictoria/logs/gt-access.log" gtoria
|
||||
|
||||
RewriteEngine On
|
||||
RewriteCond %{HTTP_HOST} !^www\. [NC]
|
||||
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
|
||||
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
|
||||
|
||||
DocumentRoot "C:/graphictoria/COMMIT_HASH/web/public"
|
||||
</VirtualHost>
|
||||
|
||||
# Blog/Wiki
|
||||
<VirtualHost *:80 *:443>
|
||||
ServerName gtoria.net
|
||||
|
||||
ServerAlias blog.gtoria.net
|
||||
ServerAlias wiki.gtoria.net
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.crt"
|
||||
SSLCertificateKeyFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.key"
|
||||
|
||||
ErrorLog "C:/xampp/logs/gt-error.log"
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Host}i\" \"%{Referer}i\" \"%{User-agent}i\"" gtoria
|
||||
CustomLog "C:/xampp/logs/gt-access.log" gtoria
|
||||
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
|
||||
|
||||
DocumentRoot "C:/graphictoria/COMMIT_HASH/web/public"
|
||||
</VirtualHost>
|
||||
|
||||
# Api endpoints.
|
||||
<VirtualHost *:80 *:443>
|
||||
ServerName gtoria.net
|
||||
|
||||
ServerAlias api.gtoria.net
|
||||
ServerAlias apis.gtoria.net
|
||||
ServerAlias assetgame.gtoria.net
|
||||
ServerAlias cdn.gtoria.net
|
||||
ServerAlias clientsettings.api.gtoria.net
|
||||
ServerAlias data.gtoria.net
|
||||
ServerAlias ecsv2.gtoria.net
|
||||
ServerAlias ephemeralcounters.api.gtoria.net
|
||||
ServerAlias gamepersistence.gtoria.net
|
||||
ServerAlias logging.service.gtoria.net
|
||||
ServerAlias setup.gtoria.net
|
||||
ServerAlias test.public.ecs.gtoria.net
|
||||
ServerAlias versioncompatibility.api.gtoria.net
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.crt"
|
||||
SSLCertificateKeyFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.key"
|
||||
|
||||
ErrorLog "C:/graphictoria/logs/gt-error.log"
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Host}i\" \"%{Referer}i\" \"%{User-agent}i\"" gtoria
|
||||
CustomLog "C:/graphictoria/logs/gt-access.log" gtoria
|
||||
|
||||
DocumentRoot "C:/graphictoria/COMMIT_HASH/web/public_api"
|
||||
</VirtualHost>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 44 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.9 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.7 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 445 KiB |
|
|
@ -0,0 +1,4 @@
|
|||
@echo off
|
||||
cd web
|
||||
|
||||
php artisan serve --port=42070
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
/node_modules
|
||||
/public/mix-manifest.json
|
||||
/public/js
|
||||
/public/css
|
||||
/public/fonts
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage
|
||||
/bootstrap/cache
|
||||
/vendor
|
||||
.env
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
/.idea
|
||||
/.vscode
|
||||
|
|
@ -1,39 +1,32 @@
|
|||
APP_NAME=VirtuBrick
|
||||
TRUSTED_HOSTS=localhost,gtoria.local
|
||||
|
||||
APP_NAME=Graphictoria
|
||||
APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://virtubrick.net
|
||||
MIX_APP_URL=http://virtubrick.net
|
||||
|
||||
IS_TEST_ENVIRONMENT=true
|
||||
|
||||
ROBLOX_COOKIE=
|
||||
|
||||
GAMESERVER_IP=127.0.0.1
|
||||
THUMBNAILER_IP=127.0.0.1
|
||||
APP_URL=http://gtoria.local
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
|
||||
RECAPTCHA_SITE_KEY=ClientKeyHere
|
||||
RECAPTCHA_SECRET_KEY=ServerKeyHere
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_CONNECTION=mysql-primary
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=virtubrick
|
||||
DB_USERNAME=root
|
||||
DB_USERNAME=service-laravel
|
||||
DB_PASSWORD=
|
||||
|
||||
DB_PRIMARY_DATABASE=gtoriadev_primary
|
||||
DB_MEMBERSHIP_DATABASE=gtoriadev_membership
|
||||
DB_FFLAG_DATABASE=gtoriadev_fflag
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
FILESYSTEM_DISK=local
|
||||
FILESYSTEM_DRIVER=local
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
MEMCACHED_HOST=memcached
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
|
|
@ -45,7 +38,7 @@ MAIL_PORT=1025
|
|||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_ADDRESS=null
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
|
|
@ -60,4 +53,4 @@ PUSHER_APP_SECRET=
|
|||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
|
@ -1,10 +1,5 @@
|
|||
* text=auto
|
||||
|
||||
*.blade.php diff=html
|
||||
*.css diff=css
|
||||
*.html diff=html
|
||||
*.md diff=markdown
|
||||
*.php diff=php
|
||||
|
||||
/.github export-ignore
|
||||
*.css linguist-vendored
|
||||
*.scss linguist-vendored
|
||||
*.js linguist-vendored
|
||||
CHANGELOG.md export-ignore
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
/node_modules
|
||||
/public/mix-manifest.json
|
||||
/public/js
|
||||
/public/css
|
||||
/public/fonts
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
|
|
@ -10,9 +6,12 @@
|
|||
.env
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
docker-compose.override.yml
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
/.idea
|
||||
/.vscode
|
||||
/public/css
|
||||
/public/js
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
php:
|
||||
preset: laravel
|
||||
version: 8
|
||||
disabled:
|
||||
- no_unused_imports
|
||||
finder:
|
||||
not-name:
|
||||
- index.php
|
||||
- server.php
|
||||
js:
|
||||
finder:
|
||||
not-name:
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
FROM node:18-alpine AS node
|
||||
FROM composer:2.3.5
|
||||
|
||||
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 /vbrick
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN mkdir ./bootstrap/cache \
|
||||
&& mkdir ./storage \
|
||||
&& mkdir ./storage/logs \
|
||||
&& mkdir ./storage/framework \
|
||||
&& mkdir ./storage/framework/cache \
|
||||
&& mkdir ./storage/framework/sessions \
|
||||
&& mkdir ./storage/framework/testing \
|
||||
&& mkdir ./storage/framework/views \
|
||||
&& mkdir ./storage/app \
|
||||
&& mkdir ./storage/app/public
|
||||
|
||||
RUN composer install \
|
||||
--no-interaction \
|
||||
--no-plugins \
|
||||
--no-scripts \
|
||||
--no-dev \
|
||||
--prefer-dist \
|
||||
&& composer dump-autoload
|
||||
|
||||
RUN npm install && npm run prod
|
||||
|
||||
RUN php artisan optimize:clear
|
||||
|
||||
CMD php artisan serve --host=0.0.0.0 --port=1024
|
||||
|
||||
EXPOSE 1024
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
## Graphictoria web
|
||||
This is the laravel Graphictoria website.
|
||||
|
|
@ -5,10 +5,17 @@ namespace App\Console;
|
|||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
use App\Jobs\UpdateUsageCounters;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* The Artisan commands provided by your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
|
|
@ -17,7 +24,7 @@ class Kernel extends ConsoleKernel
|
|||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$schedule->job(new UpdateUsageCounters)->everyMinute()->evenInMaintenanceMode();
|
||||
// $schedule->command('inspire')->hourly();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,24 +2,16 @@
|
|||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* A list of exception types with their corresponding custom log levels.
|
||||
*
|
||||
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
|
||||
*/
|
||||
protected $levels = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the exception types that are not reported.
|
||||
*
|
||||
* @var array<int, class-string<\Throwable>>
|
||||
* @var array
|
||||
*/
|
||||
protected $dontReport = [
|
||||
//
|
||||
|
|
@ -28,7 +20,7 @@ class Handler extends ExceptionHandler
|
|||
/**
|
||||
* A list of the inputs that are never flashed for validation exceptions.
|
||||
*
|
||||
* @var array<int, string>
|
||||
* @var array
|
||||
*/
|
||||
protected $dontFlash = [
|
||||
'current_password',
|
||||
|
|
@ -37,14 +29,14 @@ class Handler extends ExceptionHandler
|
|||
];
|
||||
|
||||
/**
|
||||
* Register the exception handling callbacks for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->reportable(function (Throwable $e) {
|
||||
//
|
||||
});
|
||||
}
|
||||
* Register the exception handling callbacks for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->renderable(function (NotFoundHttpException $e, $request) {
|
||||
return response()->view('main', [], 404);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2022
|
||||
Graphictoria 2022
|
||||
This file handles communications between the arbiter and the website.
|
||||
*/
|
||||
|
||||
// TODO: Comment the return values and descriptions of the soap service functions.
|
||||
// TODO: Make new classes in App\Grid to automate the generation of thumbnails and game servers.
|
||||
|
||||
namespace App\Grid;
|
||||
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use SoapClient;
|
||||
|
||||
use App\Models\ArbiterSoapFault;
|
||||
use App\Helpers\GridHelper;
|
||||
|
||||
class SoapService
|
||||
{
|
||||
/**
|
||||
|
|
@ -30,12 +30,11 @@ class SoapService
|
|||
* @param string $arbiterAddr
|
||||
* @return null
|
||||
*/
|
||||
public function __construct($arbiterType) {
|
||||
$arbiter = GridHelper::{strtolower($arbiterType) . 'Arbiter'}();
|
||||
public function __construct($arbiterAddr) {
|
||||
$this->Client = new SoapClient(
|
||||
Storage::path('grid/RCCService.wsdl'), // Arbiter WCF service WSDL should not be used for RCCService calls.
|
||||
Storage::path('grid/RCCService.wsdl'),
|
||||
[
|
||||
'location' => $arbiter,
|
||||
'location' => $arbiterAddr,
|
||||
'uri' => 'http://roblox.com/',
|
||||
'exceptions' => false
|
||||
]
|
||||
|
|
@ -53,17 +52,72 @@ class SoapService
|
|||
$soapResult = $this->Client->{$name}($args);
|
||||
|
||||
if(is_soap_fault($soapResult)) {
|
||||
ArbiterSoapFault::create([
|
||||
'function' => $name,
|
||||
'code' => $soapResult->getCode(),
|
||||
'message' => $soapResult->getMessage(),
|
||||
'job_arguments' => json_encode($args)
|
||||
]);
|
||||
// TODO: log faults
|
||||
}
|
||||
|
||||
return $soapResult;
|
||||
}
|
||||
|
||||
/* Job constructors */
|
||||
|
||||
public static function LuaValue($value)
|
||||
{
|
||||
switch ($value) {
|
||||
case is_bool(json_encode($value)) || $value == 1:
|
||||
return json_encode($value);
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
public static function CastType($value)
|
||||
{
|
||||
$luaTypeConversions = [
|
||||
'NULL' => 'LUA_TNIL',
|
||||
'boolean' => 'LUA_TBOOLEAN',
|
||||
'integer' => 'LUA_TNUMBER',
|
||||
'double' => 'LUA_TNUMBER',
|
||||
'string' => 'LUA_TSTRING',
|
||||
'array' => 'LUA_TTABLE',
|
||||
'object' => 'LUA_TNIL'
|
||||
];
|
||||
return $luaTypeConversions[gettype($value)];
|
||||
}
|
||||
|
||||
public static function ToLuaArguments($luaArguments = [])
|
||||
{
|
||||
$luaValue = ['LuaValue' => []];
|
||||
|
||||
foreach ($luaArguments as $argument) {
|
||||
array_push(
|
||||
$luaValue['LuaValue'],
|
||||
[
|
||||
'type' => SoapService::CastType($argument),
|
||||
'value' => SoapService::LuaValue($argument)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return $luaValue;
|
||||
}
|
||||
|
||||
public static function MakeJobJSON($jobID, $expiration, $category, $cores, $scriptName, $script, $scriptArgs = [])
|
||||
{
|
||||
return [
|
||||
'job' => [
|
||||
'id' => $jobID,
|
||||
'expirationInSeconds' => $expiration,
|
||||
'category' => $category,
|
||||
'cores' => $cores
|
||||
],
|
||||
'script' => [
|
||||
'name' => $scriptName,
|
||||
'script' => $script,
|
||||
'arguments' => SoapService::ToLuaArguments($scriptArgs)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/* Service functions */
|
||||
|
||||
public function HelloWorld()
|
||||
|
|
|
|||
|
|
@ -1,140 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2022
|
||||
Asset Helper
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use GuzzleHttp\Cookie\CookieJar;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
use App\Helpers\CdnHelper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetVersion;
|
||||
use App\Models\RobloxAsset;
|
||||
use App\Models\UserAsset;
|
||||
|
||||
class AssetHelper
|
||||
{
|
||||
private static function cookiedRequest()
|
||||
{
|
||||
$cookieJar = CookieJar::fromArray([
|
||||
'.ROBLOXSECURITY' => env('app.robloxcookie')
|
||||
], '.roblox.com');
|
||||
|
||||
return Http::withOptions(['cookies' => $cookieJar, 'headers' => ['User-Agent' => 'Roblox/WinInet', 'Requester' => 'Server']]);
|
||||
}
|
||||
|
||||
public static function newAsset($props, $hash)
|
||||
{
|
||||
$asset = Asset::create($props);
|
||||
$assetVersion = AssetVersion::create([
|
||||
'parentAsset' => $asset->id,
|
||||
'localVersion' => 1,
|
||||
'contentURL' => $hash
|
||||
]);
|
||||
$asset->assetVersionId = $assetVersion->id;
|
||||
$asset->save();
|
||||
|
||||
UserAsset::createSerialed($asset->creatorId, $asset->id);
|
||||
|
||||
return $asset;
|
||||
}
|
||||
|
||||
private static function getRBXMarketplaceInfo($assetId)
|
||||
{
|
||||
$marketplaceResult = self::cookiedRequest()->get('https://api.roblox.com/marketplace/productinfo?assetId=' . $assetId);
|
||||
|
||||
if(!$marketplaceResult->ok())
|
||||
return false;
|
||||
|
||||
$marketplaceResult = $marketplaceResult->json();
|
||||
$assetTypeId = $marketplaceResult['AssetTypeId'];
|
||||
if(
|
||||
$assetTypeId == 41 || // Hair Accessory
|
||||
$assetTypeId == 42 || // Face Accessory
|
||||
$assetTypeId == 43 || // Neck Accessory
|
||||
$assetTypeId == 44 || // Shoulder Accessory
|
||||
$assetTypeId == 45 || // Front Accessory
|
||||
$assetTypeId == 46 || // Back Accessory
|
||||
$assetTypeId == 47 // Waist Accessory
|
||||
) {
|
||||
$assetTypeId = 8;
|
||||
}
|
||||
|
||||
$marketplaceResult['AssetTypeId'] = $assetTypeId;
|
||||
|
||||
return $marketplaceResult;
|
||||
}
|
||||
|
||||
public static function uploadRobloxAsset($id, $uploadToHolder = false)
|
||||
{
|
||||
{
|
||||
$uploadedAsset = RobloxAsset::where('robloxAssetId', $id)->first();
|
||||
if($uploadedAsset)
|
||||
return $uploadedAsset->asset;
|
||||
}
|
||||
|
||||
$marketplaceResult = self::getRBXMarketplaceInfo($id);
|
||||
$assetResult = self::cookiedRequest()->get('https://assetdelivery.roblox.com/v2/asset?id=' . $id);
|
||||
|
||||
if(!$marketplaceResult || !$assetResult->ok())
|
||||
return false;
|
||||
|
||||
$assetContent = Http::get($assetResult['locations'][0]['location']);
|
||||
$hash = CdnHelper::SaveContent($assetContent->body(), $assetContent->header('Content-Type'));
|
||||
$asset = self::newAsset([
|
||||
'creatorId' => ($uploadToHolder ? 1 : Auth::user()->id),
|
||||
'name' => $marketplaceResult['Name'],
|
||||
'description' => $marketplaceResult['Description'],
|
||||
'approved' => true,
|
||||
'priceInTokens' => $marketplaceResult['PriceInRobux'] ?: 0,
|
||||
'onSale' => $marketplaceResult['IsForSale'],
|
||||
'assetTypeId' => $marketplaceResult['AssetTypeId'],
|
||||
'assetVersionId' => 0
|
||||
], $hash);
|
||||
|
||||
RobloxAsset::create([
|
||||
'robloxAssetId' => $id,
|
||||
'localAssetId' => $asset->id
|
||||
]);
|
||||
|
||||
return $asset;
|
||||
}
|
||||
|
||||
public static function uploadCustomRobloxAsset($id, $uploadToHolder = false, $b64Content)
|
||||
{
|
||||
{
|
||||
$uploadedAsset = RobloxAsset::where('robloxAssetId', $id)->first();
|
||||
if($uploadedAsset)
|
||||
return $uploadedAsset->asset;
|
||||
}
|
||||
|
||||
$marketplaceResult = self::getRBXMarketplaceInfo($id);
|
||||
|
||||
if(!$marketplaceResult)
|
||||
return false;
|
||||
|
||||
$hash = CdnHelper::SaveContentB64($b64Content, 'application/octet-stream');
|
||||
$asset = self::newAsset([
|
||||
'creatorId' => ($uploadToHolder ? 1 : Auth::user()->id),
|
||||
'name' => $marketplaceResult['Name'],
|
||||
'description' => $marketplaceResult['Description'],
|
||||
'approved' => true,
|
||||
'priceInTokens' => $marketplaceResult['PriceInRobux'] ?: 0,
|
||||
'onSale' => $marketplaceResult['IsForSale'],
|
||||
'assetTypeId' => $marketplaceResult['AssetTypeId'],
|
||||
'assetVersionId' => 0
|
||||
], $hash);
|
||||
|
||||
RobloxAsset::create([
|
||||
'robloxAssetId' => $id,
|
||||
'localAssetId' => $asset->id
|
||||
]);
|
||||
|
||||
return $asset;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Graphictoria 2022
|
||||
Authentication helper
|
||||
Written because FUCK WHOEVER IS BEHIND THE Illuminate\Foundation\Auth\User DEV TEAM AHHHHHH
|
||||
my frustration is immeasureable ~ xlxi
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Carbon\Carbon;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\User\UserSession;
|
||||
use App\Helpers\Random;
|
||||
|
||||
class AuthHelper
|
||||
{
|
||||
/**
|
||||
* "Guards" a page in the sense where it kills the request if the user is logged in.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function Guard(Request $request) {
|
||||
if(AuthHelper::GetCurrentUser($request))
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current user.
|
||||
*
|
||||
* @return User?
|
||||
*/
|
||||
public static function GetCurrentUser(Request $request) {
|
||||
if($request->session()->exists('authentication')) {
|
||||
$session = UserSession::where('token', $request->session()->get('authentication'))->first();
|
||||
|
||||
if($session)
|
||||
return User::where('id', $session->user)->first();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a session.
|
||||
*
|
||||
* @return User?
|
||||
*/
|
||||
public static function RemoveSession(Request $request) {
|
||||
if($request->session()->exists('authentication')) {
|
||||
$session = UserSession::where('token', $request->session()->get('authentication'))->first();
|
||||
$session->delete();
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants a session.
|
||||
*
|
||||
* @return UserSession
|
||||
*/
|
||||
public static function GrantSession($request, $id) {
|
||||
$session = new UserSession();
|
||||
$session->user = $id;
|
||||
// formerly cookies
|
||||
$session->token = 'DO_NOT_SHARE_OR_YOUR_ITEMS_WILL_BE_STOLEN_|' . Random::Str(64);
|
||||
$session->ip = $request->ip();
|
||||
$session->last_seen = Carbon::now();
|
||||
$session->save();
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,851 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2023
|
||||
Brick color helper.
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class BrickColorHelper
|
||||
{
|
||||
private static $brickColors = [
|
||||
1 => [
|
||||
'Color' => [242, 243, 243],
|
||||
'Name' => 'White'
|
||||
],
|
||||
2 => [
|
||||
'Color' => [161, 165, 162],
|
||||
'Name' => 'Grey'
|
||||
],
|
||||
3 => [
|
||||
'Color' => [249, 233, 153],
|
||||
'Name' => 'Light yellow'
|
||||
],
|
||||
5 => [
|
||||
'Color' => [215, 197, 154],
|
||||
'Name' => 'Brick yellow'
|
||||
],
|
||||
6 => [
|
||||
'Color' => [194, 218, 184],
|
||||
'Name' => 'Light green (Mint)'
|
||||
],
|
||||
9 => [
|
||||
'Color' => [232, 186, 200],
|
||||
'Name' => 'Light reddish violet'
|
||||
],
|
||||
11 => [
|
||||
'Color' => [0x80, 0xbb, 0xdb],
|
||||
'Name' => 'Pastel Blue'
|
||||
],
|
||||
12 => [
|
||||
'Color' => [203, 132, 66],
|
||||
'Name' => 'Light orange brown'
|
||||
],
|
||||
18 => [
|
||||
'Color' => [204, 142, 105],
|
||||
'Name' => 'Nougat'
|
||||
],
|
||||
21 => [
|
||||
'Color' => [196, 40, 28],
|
||||
'Name' => 'Bright red'
|
||||
],
|
||||
22 => [
|
||||
'Color' => [196, 112, 160],
|
||||
'Name' => 'Med. reddish violet'
|
||||
],
|
||||
23 => [
|
||||
'Color' => [13, 105, 172],
|
||||
'Name' => 'Bright blue'
|
||||
],
|
||||
24 => [
|
||||
'Color' => [245, 205, 48],
|
||||
'Name' => 'Bright yellow'
|
||||
],
|
||||
25 => [
|
||||
'Color' => [98, 71, 50],
|
||||
'Name' => 'Earth orange'
|
||||
],
|
||||
26 => [
|
||||
'Color' => [27, 42, 53],
|
||||
'Name' => 'Black'
|
||||
],
|
||||
27 => [
|
||||
'Color' => [109, 110, 108],
|
||||
'Name' => 'Dark grey'
|
||||
],
|
||||
28 => [
|
||||
'Color' => [40, 127, 71],
|
||||
'Name' => 'Dark green'
|
||||
],
|
||||
29 => [
|
||||
'Color' => [161, 196, 140],
|
||||
'Name' => 'Medium green'
|
||||
],
|
||||
36 => [
|
||||
'Color' => [243, 207, 155],
|
||||
'Name' => 'Lig. Yellowich orange'
|
||||
],
|
||||
37 => [
|
||||
'Color' => [75, 151, 75],
|
||||
'Name' => 'Bright green'
|
||||
],
|
||||
38 => [
|
||||
'Color' => [160, 95, 53],
|
||||
'Name' => 'Dark orange'
|
||||
],
|
||||
39 => [
|
||||
'Color' => [193, 202, 222],
|
||||
'Name' => 'Light bluish violet'
|
||||
],
|
||||
40 => [
|
||||
'Color' => [236, 236, 236],
|
||||
'Name' => 'Transparent'
|
||||
],
|
||||
41 => [
|
||||
'Color' => [205, 84, 75],
|
||||
'Name' => 'Tr. Red'
|
||||
],
|
||||
42 => [
|
||||
'Color' => [193, 223, 240],
|
||||
'Name' => 'Tr. Lg blue'
|
||||
],
|
||||
43 => [
|
||||
'Color' => [123, 182, 232],
|
||||
'Name' => 'Tr. Blue'
|
||||
],
|
||||
44 => [
|
||||
'Color' => [247, 241, 141],
|
||||
'Name' => 'Tr. Yellow'
|
||||
],
|
||||
45 => [
|
||||
'Color' => [180, 210, 228],
|
||||
'Name' => 'Light blue'
|
||||
],
|
||||
47 => [
|
||||
'Color' => [217, 133, 108],
|
||||
'Name' => 'Tr. Flu. Reddish orange'
|
||||
],
|
||||
48 => [
|
||||
'Color' => [132, 182, 141],
|
||||
'Name' => 'Tr. Green'
|
||||
],
|
||||
49 => [
|
||||
'Color' => [248, 241, 132],
|
||||
'Name' => 'Tr. Flu. Green'
|
||||
],
|
||||
50 => [
|
||||
'Color' => [236, 232, 222],
|
||||
'Name' => 'Phosph. White'
|
||||
],
|
||||
100 => [
|
||||
'Color' => [238, 196, 182],
|
||||
'Name' => 'Light red'
|
||||
],
|
||||
101 => [
|
||||
'Color' => [218, 134, 122],
|
||||
'Name' => 'Medium red'
|
||||
],
|
||||
102 => [
|
||||
'Color' => [110, 153, 202],
|
||||
'Name' => 'Medium blue'
|
||||
],
|
||||
103 => [
|
||||
'Color' => [199, 193, 183],
|
||||
'Name' => 'Light grey'
|
||||
],
|
||||
104 => [
|
||||
'Color' => [107, 50, 124],
|
||||
'Name' => 'Bright violet'
|
||||
],
|
||||
105 => [
|
||||
'Color' => [226, 155, 64],
|
||||
'Name' => 'Br. yellowish orange'
|
||||
],
|
||||
106 => [
|
||||
'Color' => [218, 133, 65],
|
||||
'Name' => 'Bright orange'
|
||||
],
|
||||
107 => [
|
||||
'Color' => [0, 143, 156],
|
||||
'Name' => 'Bright bluish green'
|
||||
],
|
||||
108 => [
|
||||
'Color' => [104, 92, 67],
|
||||
'Name' => 'Earth yellow'
|
||||
],
|
||||
110 => [
|
||||
'Color' => [67, 84, 147],
|
||||
'Name' => 'Bright bluish violet'
|
||||
],
|
||||
111 => [
|
||||
'Color' => [191, 183, 177],
|
||||
'Name' => 'Tr. Brown'
|
||||
],
|
||||
112 => [
|
||||
'Color' => [104, 116, 172],
|
||||
'Name' => 'Medium bluish violet'
|
||||
],
|
||||
113 => [
|
||||
'Color' => [228, 173, 200],
|
||||
'Name' => 'Tr. Medi. reddish violet'
|
||||
],
|
||||
115 => [
|
||||
'Color' => [199, 210, 60],
|
||||
'Name' => 'Med. yellowish green'
|
||||
],
|
||||
116 => [
|
||||
'Color' => [85, 165, 175],
|
||||
'Name' => 'Med. bluish green'
|
||||
],
|
||||
118 => [
|
||||
'Color' => [183, 215, 213],
|
||||
'Name' => 'Light bluish green'
|
||||
],
|
||||
119 => [
|
||||
'Color' => [164, 189, 71],
|
||||
'Name' => 'Br. yellowish green'
|
||||
],
|
||||
120 => [
|
||||
'Color' => [217, 228, 167],
|
||||
'Name' => 'Lig. yellowish green'
|
||||
],
|
||||
121 => [
|
||||
'Color' => [231, 172, 88],
|
||||
'Name' => 'Med. yellowish orange'
|
||||
],
|
||||
123 => [
|
||||
'Color' => [211, 111, 76],
|
||||
'Name' => 'Br. reddish orange'
|
||||
],
|
||||
124 => [
|
||||
'Color' => [146, 57, 120],
|
||||
'Name' => 'Bright reddish violet'
|
||||
],
|
||||
125 => [
|
||||
'Color' => [234, 184, 146],
|
||||
'Name' => 'Light orange'
|
||||
],
|
||||
126 => [
|
||||
'Color' => [165, 165, 203],
|
||||
'Name' => 'Tr. Bright bluish violet'
|
||||
],
|
||||
127 => [
|
||||
'Color' => [220, 188, 129],
|
||||
'Name' => 'Gold'
|
||||
],
|
||||
128 => [
|
||||
'Color' => [174, 122, 89],
|
||||
'Name' => 'Dark nougat'
|
||||
],
|
||||
131 => [
|
||||
'Color' => [156, 163, 168],
|
||||
'Name' => 'Silver'
|
||||
],
|
||||
133 => [
|
||||
'Color' => [213, 115, 61],
|
||||
'Name' => 'Neon orange'
|
||||
],
|
||||
134 => [
|
||||
'Color' => [216, 221, 86],
|
||||
'Name' => 'Neon green'
|
||||
],
|
||||
135 => [
|
||||
'Color' => [116, 134, 157],
|
||||
'Name' => 'Sand blue'
|
||||
],
|
||||
136 => [
|
||||
'Color' => [135, 124, 144],
|
||||
'Name' => 'Sand violet'
|
||||
],
|
||||
137 => [
|
||||
'Color' => [224, 152, 100],
|
||||
'Name' => 'Medium orange'
|
||||
],
|
||||
138 => [
|
||||
'Color' => [149, 138, 115],
|
||||
'Name' => 'Sand yellow'
|
||||
],
|
||||
140 => [
|
||||
'Color' => [32, 58, 86],
|
||||
'Name' => 'Earth blue'
|
||||
],
|
||||
141 => [
|
||||
'Color' => [39, 70, 45],
|
||||
'Name' => 'Earth green'
|
||||
],
|
||||
143 => [
|
||||
'Color' => [207, 226, 247],
|
||||
'Name' => 'Tr. Flu. Blue'
|
||||
],
|
||||
145 => [
|
||||
'Color' => [121, 136, 161],
|
||||
'Name' => 'Sand blue metallic'
|
||||
],
|
||||
146 => [
|
||||
'Color' => [149, 142, 163],
|
||||
'Name' => 'Sand violet metallic'
|
||||
],
|
||||
147 => [
|
||||
'Color' => [147, 135, 103],
|
||||
'Name' => 'Sand yellow metallic'
|
||||
],
|
||||
148 => [
|
||||
'Color' => [87, 88, 87],
|
||||
'Name' => 'Dark grey metallic'
|
||||
],
|
||||
149 => [
|
||||
'Color' => [22, 29, 50],
|
||||
'Name' => 'Black metallic'
|
||||
],
|
||||
150 => [
|
||||
'Color' => [171, 173, 172],
|
||||
'Name' => 'Light grey metallic'
|
||||
],
|
||||
151 => [
|
||||
'Color' => [120, 144, 130],
|
||||
'Name' => 'Sand green'
|
||||
],
|
||||
153 => [
|
||||
'Color' => [149, 121, 119],
|
||||
'Name' => 'Sand red'
|
||||
],
|
||||
154 => [
|
||||
'Color' => [123, 46, 47],
|
||||
'Name' => 'Dark red'
|
||||
],
|
||||
157 => [
|
||||
'Color' => [255, 246, 123],
|
||||
'Name' => 'Tr. Flu. Yellow'
|
||||
],
|
||||
158 => [
|
||||
'Color' => [225, 164, 194],
|
||||
'Name' => 'Tr. Flu. Red'
|
||||
],
|
||||
168 => [
|
||||
'Color' => [117, 108, 98],
|
||||
'Name' => 'Gun metallic'
|
||||
],
|
||||
176 => [
|
||||
'Color' => [151, 105, 91],
|
||||
'Name' => 'Red flip/flop'
|
||||
],
|
||||
178 => [
|
||||
'Color' => [180, 132, 85],
|
||||
'Name' => 'Yellow flip/flop'
|
||||
],
|
||||
179 => [
|
||||
'Color' => [137, 135, 136],
|
||||
'Name' => 'Silver flip/flop'
|
||||
],
|
||||
180 => [
|
||||
'Color' => [215, 169, 75],
|
||||
'Name' => 'Curry'
|
||||
],
|
||||
190 => [
|
||||
'Color' => [249, 214, 46],
|
||||
'Name' => 'Fire Yellow'
|
||||
],
|
||||
191 => [
|
||||
'Color' => [232, 171, 45],
|
||||
'Name' => 'Flame yellowish orange'
|
||||
],
|
||||
192 => [
|
||||
'Color' => [105, 64, 40],
|
||||
'Name' => 'Reddish brown'
|
||||
],
|
||||
193 => [
|
||||
'Color' => [207, 96, 36],
|
||||
'Name' => 'Flame reddish orange'
|
||||
],
|
||||
194 => [
|
||||
'Color' => [163, 162, 165],
|
||||
'Name' => 'Medium stone grey'
|
||||
],
|
||||
195 => [
|
||||
'Color' => [70, 103, 164],
|
||||
'Name' => 'Royal blue'
|
||||
],
|
||||
196 => [
|
||||
'Color' => [35, 71, 139],
|
||||
'Name' => 'Dark Royal blue'
|
||||
],
|
||||
198 => [
|
||||
'Color' => [142, 66, 133],
|
||||
'Name' => 'Bright reddish lilac'
|
||||
],
|
||||
199 => [
|
||||
'Color' => [99, 95, 98],
|
||||
'Name' => 'Dark stone grey'
|
||||
],
|
||||
200 => [
|
||||
'Color' => [130, 138, 93],
|
||||
'Name' => 'Lemon metalic'
|
||||
],
|
||||
208 => [
|
||||
'Color' => [229, 228, 223],
|
||||
'Name' => 'Light stone grey'
|
||||
],
|
||||
209 => [
|
||||
'Color' => [176, 142, 68],
|
||||
'Name' => 'Dark Curry'
|
||||
],
|
||||
210 => [
|
||||
'Color' => [112, 149, 120],
|
||||
'Name' => 'Faded green'
|
||||
],
|
||||
211 => [
|
||||
'Color' => [121, 181, 181],
|
||||
'Name' => 'Turquoise'
|
||||
],
|
||||
212 => [
|
||||
'Color' => [159, 195, 233],
|
||||
'Name' => 'Light Royal blue'
|
||||
],
|
||||
213 => [
|
||||
'Color' => [108, 129, 183],
|
||||
'Name' => 'Medium Royal blue'
|
||||
],
|
||||
216 => [
|
||||
'Color' => [143, 76, 42],
|
||||
'Name' => 'Rust'
|
||||
],
|
||||
217 => [
|
||||
'Color' => [124, 92, 70],
|
||||
'Name' => 'Brown'
|
||||
],
|
||||
218 => [
|
||||
'Color' => [150, 112, 159],
|
||||
'Name' => 'Reddish lilac'
|
||||
],
|
||||
219 => [
|
||||
'Color' => [107, 98, 155],
|
||||
'Name' => 'Lilac'
|
||||
],
|
||||
220 => [
|
||||
'Color' => [167, 169, 206],
|
||||
'Name' => 'Light lilac'
|
||||
],
|
||||
221 => [
|
||||
'Color' => [205, 98, 152],
|
||||
'Name' => 'Bright purple'
|
||||
],
|
||||
222 => [
|
||||
'Color' => [228, 173, 200],
|
||||
'Name' => 'Light purple'
|
||||
],
|
||||
223 => [
|
||||
'Color' => [220, 144, 149],
|
||||
'Name' => 'Light pink'
|
||||
],
|
||||
224 => [
|
||||
'Color' => [240, 213, 160],
|
||||
'Name' => 'Light brick yellow'
|
||||
],
|
||||
225 => [
|
||||
'Color' => [235, 184, 127],
|
||||
'Name' => 'Warm yellowish orange'
|
||||
],
|
||||
226 => [
|
||||
'Color' => [253, 234, 141],
|
||||
'Name' => 'Cool yellow'
|
||||
],
|
||||
232 => [
|
||||
'Color' => [125, 187, 221],
|
||||
'Name' => 'Dove blue'
|
||||
],
|
||||
268 => [
|
||||
'Color' => [52, 43, 117],
|
||||
'Name' => 'Medium lilac'
|
||||
],
|
||||
301 => [
|
||||
'Color' => [80, 109, 84],
|
||||
'Name' => 'Slime green'
|
||||
],
|
||||
302 => [
|
||||
'Color' => [91, 93, 105],
|
||||
'Name' => 'Smoky grey'
|
||||
],
|
||||
303 => [
|
||||
'Color' => [0, 16, 176],
|
||||
'Name' => 'Dark blue'
|
||||
],
|
||||
304 => [
|
||||
'Color' => [44, 101, 29],
|
||||
'Name' => 'Parsley green'
|
||||
],
|
||||
305 => [
|
||||
'Color' => [82, 124, 174],
|
||||
'Name' => 'Steel blue'
|
||||
],
|
||||
306 => [
|
||||
'Color' => [51, 88, 130],
|
||||
'Name' => 'Storm blue'
|
||||
],
|
||||
307 => [
|
||||
'Color' => [16, 42, 220],
|
||||
'Name' => 'Lapis'
|
||||
],
|
||||
308 => [
|
||||
'Color' => [61, 21, 133],
|
||||
'Name' => 'Dark indigo'
|
||||
],
|
||||
309 => [
|
||||
'Color' => [52, 142, 64],
|
||||
'Name' => 'Sea green'
|
||||
],
|
||||
310 => [
|
||||
'Color' => [91, 154, 76],
|
||||
'Name' => 'Shamrock'
|
||||
],
|
||||
311 => [
|
||||
'Color' => [159, 161, 172],
|
||||
'Name' => 'Fossil'
|
||||
],
|
||||
312 => [
|
||||
'Color' => [89, 34, 89],
|
||||
'Name' => 'Mulberry'
|
||||
],
|
||||
313 => [
|
||||
'Color' => [31, 128, 29],
|
||||
'Name' => 'Forest green'
|
||||
],
|
||||
314 => [
|
||||
'Color' => [159, 173, 192],
|
||||
'Name' => 'Cadet blue'
|
||||
],
|
||||
315 => [
|
||||
'Color' => [9, 137, 207],
|
||||
'Name' => 'Electric blue'
|
||||
],
|
||||
316 => [
|
||||
'Color' => [123, 0, 123],
|
||||
'Name' => 'Eggplant'
|
||||
],
|
||||
317 => [
|
||||
'Color' => [124, 156, 107],
|
||||
'Name' => 'Moss'
|
||||
],
|
||||
318 => [
|
||||
'Color' => [138, 171, 133],
|
||||
'Name' => 'Artichoke'
|
||||
],
|
||||
319 => [
|
||||
'Color' => [185, 196, 177],
|
||||
'Name' => 'Sage green'
|
||||
],
|
||||
320 => [
|
||||
'Color' => [202, 203, 209],
|
||||
'Name' => 'Ghost grey'
|
||||
],
|
||||
321 => [
|
||||
'Color' => [167, 94, 155],
|
||||
'Name' => 'Lilac'
|
||||
],
|
||||
322 => [
|
||||
'Color' => [123, 47, 123],
|
||||
'Name' => 'Plum'
|
||||
],
|
||||
323 => [
|
||||
'Color' => [148, 190, 129],
|
||||
'Name' => 'Olivine'
|
||||
],
|
||||
324 => [
|
||||
'Color' => [168, 189, 153],
|
||||
'Name' => 'Laurel green'
|
||||
],
|
||||
325 => [
|
||||
'Color' => [223, 223, 222],
|
||||
'Name' => 'Quill grey'
|
||||
],
|
||||
327 => [
|
||||
'Color' => [151, 0, 0],
|
||||
'Name' => 'Crimson'
|
||||
],
|
||||
328 => [
|
||||
'Color' => [177, 229, 166],
|
||||
'Name' => 'Mint'
|
||||
],
|
||||
329 => [
|
||||
'Color' => [152, 194, 219],
|
||||
'Name' => 'Baby blue'
|
||||
],
|
||||
330 => [
|
||||
'Color' => [255, 152, 220],
|
||||
'Name' => 'Carnation pink'
|
||||
],
|
||||
331 => [
|
||||
'Color' => [255, 89, 89],
|
||||
'Name' => 'Persimmon'
|
||||
],
|
||||
332 => [
|
||||
'Color' => [117, 0, 0],
|
||||
'Name' => 'Maroon'
|
||||
],
|
||||
333 => [
|
||||
'Color' => [239, 184, 56],
|
||||
'Name' => 'Gold'
|
||||
],
|
||||
334 => [
|
||||
'Color' => [248, 217, 109],
|
||||
'Name' => 'Daisy orange'
|
||||
],
|
||||
335 => [
|
||||
'Color' => [231, 231, 236],
|
||||
'Name' => 'Pearl'
|
||||
],
|
||||
336 => [
|
||||
'Color' => [199, 212, 228],
|
||||
'Name' => 'Fog'
|
||||
],
|
||||
337 => [
|
||||
'Color' => [255, 148, 148],
|
||||
'Name' => 'Salmon'
|
||||
],
|
||||
338 => [
|
||||
'Color' => [190, 104, 98],
|
||||
'Name' => 'Terra Cotta'
|
||||
],
|
||||
339 => [
|
||||
'Color' => [86, 36, 36],
|
||||
'Name' => 'Cocoa'
|
||||
],
|
||||
340 => [
|
||||
'Color' => [241, 231, 199],
|
||||
'Name' => 'Wheat'
|
||||
],
|
||||
341 => [
|
||||
'Color' => [254, 243, 187],
|
||||
'Name' => 'Buttermilk'
|
||||
],
|
||||
342 => [
|
||||
'Color' => [224, 178, 208],
|
||||
'Name' => 'Mauve'
|
||||
],
|
||||
343 => [
|
||||
'Color' => [212, 144, 189],
|
||||
'Name' => 'Sunrise'
|
||||
],
|
||||
344 => [
|
||||
'Color' => [150, 85, 85],
|
||||
'Name' => 'Tawny'
|
||||
],
|
||||
345 => [
|
||||
'Color' => [143, 76, 42],
|
||||
'Name' => 'Rust'
|
||||
],
|
||||
346 => [
|
||||
'Color' => [211, 190, 150],
|
||||
'Name' => 'Cashmere'
|
||||
],
|
||||
347 => [
|
||||
'Color' => [226, 220, 188],
|
||||
'Name' => 'Khaki'
|
||||
],
|
||||
348 => [
|
||||
'Color' => [237, 234, 234],
|
||||
'Name' => 'Lily white'
|
||||
],
|
||||
349 => [
|
||||
'Color' => [233, 218, 218],
|
||||
'Name' => 'Seashell'
|
||||
],
|
||||
350 => [
|
||||
'Color' => [136, 62, 62],
|
||||
'Name' => 'Burgundy'
|
||||
],
|
||||
351 => [
|
||||
'Color' => [188, 155, 93],
|
||||
'Name' => 'Cork'
|
||||
],
|
||||
352 => [
|
||||
'Color' => [199, 172, 120],
|
||||
'Name' => 'Burlap'
|
||||
],
|
||||
353 => [
|
||||
'Color' => [202, 191, 163],
|
||||
'Name' => 'Beige'
|
||||
],
|
||||
354 => [
|
||||
'Color' => [187, 179, 178],
|
||||
'Name' => 'Oyster'
|
||||
],
|
||||
355 => [
|
||||
'Color' => [108, 88, 75],
|
||||
'Name' => 'Pine Cone'
|
||||
],
|
||||
356 => [
|
||||
'Color' => [160, 132, 79],
|
||||
'Name' => 'Fawn brown'
|
||||
],
|
||||
357 => [
|
||||
'Color' => [149, 137, 136],
|
||||
'Name' => 'Hurricane grey'
|
||||
],
|
||||
358 => [
|
||||
'Color' => [171, 168, 158],
|
||||
'Name' => 'Cloudy grey'
|
||||
],
|
||||
359 => [
|
||||
'Color' => [175, 148, 131],
|
||||
'Name' => 'Linen'
|
||||
],
|
||||
360 => [
|
||||
'Color' => [150, 103, 102],
|
||||
'Name' => 'Copper'
|
||||
],
|
||||
361 => [
|
||||
'Color' => [86, 66, 54],
|
||||
'Name' => 'Dirt brown'
|
||||
],
|
||||
362 => [
|
||||
'Color' => [126, 104, 63],
|
||||
'Name' => 'Bronze'
|
||||
],
|
||||
363 => [
|
||||
'Color' => [105, 102, 92],
|
||||
'Name' => 'Flint'
|
||||
],
|
||||
364 => [
|
||||
'Color' => [90, 76, 66],
|
||||
'Name' => 'Dark taupe'
|
||||
],
|
||||
365 => [
|
||||
'Color' => [106, 57, 9],
|
||||
'Name' => 'Burnt Sienna'
|
||||
],
|
||||
1001 => [
|
||||
'Color' => [248, 248, 248],
|
||||
'Name' => 'Institutional white'
|
||||
],
|
||||
1002 => [
|
||||
'Color' => [205, 205, 205],
|
||||
'Name' => 'Mid gray'
|
||||
],
|
||||
1003 => [
|
||||
'Color' => [17, 17, 17],
|
||||
'Name' => 'Really black'
|
||||
],
|
||||
1004 => [
|
||||
'Color' => [255, 0, 0],
|
||||
'Name' => 'Really red'
|
||||
],
|
||||
1005 => [
|
||||
'Color' => [255, 175, 0],
|
||||
'Name' => 'Deep orange'
|
||||
],
|
||||
1006 => [
|
||||
'Color' => [180, 128, 255],
|
||||
'Name' => 'Alder'
|
||||
],
|
||||
1007 => [
|
||||
'Color' => [163, 75, 75],
|
||||
'Name' => 'Dusty Rose'
|
||||
],
|
||||
1008 => [
|
||||
'Color' => [193, 190, 66],
|
||||
'Name' => 'Olive'
|
||||
],
|
||||
1009 => [
|
||||
'Color' => [255, 255, 0],
|
||||
'Name' => 'New Yeller'
|
||||
],
|
||||
1010 => [
|
||||
'Color' => [0, 0, 255],
|
||||
'Name' => 'Really blue'
|
||||
],
|
||||
1011 => [
|
||||
'Color' => [0, 32, 96],
|
||||
'Name' => 'Navy blue'
|
||||
],
|
||||
1012 => [
|
||||
'Color' => [33, 84, 185],
|
||||
'Name' => 'Deep blue'
|
||||
],
|
||||
1013 => [
|
||||
'Color' => [4, 175, 236],
|
||||
'Name' => 'Cyan'
|
||||
],
|
||||
1014 => [
|
||||
'Color' => [170, 85, 0],
|
||||
'Name' => 'CGA brown'
|
||||
],
|
||||
1015 => [
|
||||
'Color' => [170, 0, 170],
|
||||
'Name' => 'Magenta'
|
||||
],
|
||||
1016 => [
|
||||
'Color' => [255, 102, 204],
|
||||
'Name' => 'Pink'
|
||||
],
|
||||
1017 => [
|
||||
'Color' => [255, 175, 0],
|
||||
'Name' => 'Deep orange'
|
||||
],
|
||||
1018 => [
|
||||
'Color' => [18, 238, 212],
|
||||
'Name' => 'Teal'
|
||||
],
|
||||
1019 => [
|
||||
'Color' => [0, 255, 255],
|
||||
'Name' => 'Toothpaste'
|
||||
],
|
||||
1020 => [
|
||||
'Color' => [0, 255, 0],
|
||||
'Name' => 'Lime green'
|
||||
],
|
||||
1021 => [
|
||||
'Color' => [58, 125, 21],
|
||||
'Name' => 'Camo'
|
||||
],
|
||||
1022 => [
|
||||
'Color' => [127, 142, 100],
|
||||
'Name' => 'Grime'
|
||||
],
|
||||
1023 => [
|
||||
'Color' => [140, 91, 159],
|
||||
'Name' => 'Lavender'
|
||||
],
|
||||
1024 => [
|
||||
'Color' => [175, 221, 255],
|
||||
'Name' => 'Pastel light blue'
|
||||
],
|
||||
1025 => [
|
||||
'Color' => [255, 201, 201],
|
||||
'Name' => 'Pastel orange'
|
||||
],
|
||||
1026 => [
|
||||
'Color' => [177, 167, 255],
|
||||
'Name' => 'Pastel violet'
|
||||
],
|
||||
1027 => [
|
||||
'Color' => [159, 243, 233],
|
||||
'Name' => 'Pastel blue-green'
|
||||
],
|
||||
1028 => [
|
||||
'Color' => [204, 255, 204],
|
||||
'Name' => 'Pastel green'
|
||||
],
|
||||
1029 => [
|
||||
'Color' => [255, 255, 204],
|
||||
'Name' => 'Pastel yellow'
|
||||
],
|
||||
1030 => [
|
||||
'Color' => [255, 204, 153],
|
||||
'Name' => 'Pastel brown'
|
||||
],
|
||||
1031 => [
|
||||
'Color' => [98, 37, 209],
|
||||
'Name' => 'Royal purple'
|
||||
],
|
||||
1032 => [
|
||||
'Color' => [255, 0, 191],
|
||||
'Name' => 'Hot pink'
|
||||
]
|
||||
];
|
||||
|
||||
public static function IsValidColor($colorId)
|
||||
{
|
||||
return array_key_exists($colorId, self::$brickColors);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Graphictoria 2022
|
||||
JSON Pretty Printer
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class COMHelper
|
||||
{
|
||||
public static function isCOM() {
|
||||
return (php_sapi_name() === 'cli');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2022
|
||||
CDN helper.
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Models\CdnHash;
|
||||
|
||||
class CdnHelper
|
||||
{
|
||||
public static function GetDisk()
|
||||
{
|
||||
return Storage::build([
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/content'),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function Hash($content)
|
||||
{
|
||||
return hash('sha256', $content);
|
||||
}
|
||||
|
||||
public static function SaveContent($content, $mime)
|
||||
{
|
||||
$disk = self::GetDisk();
|
||||
$hash = self::Hash($content);
|
||||
|
||||
if(!$disk->exists($hash) || !CdnHash::where('hash', $hash)->exists()) {
|
||||
$disk->put($hash, $content);
|
||||
|
||||
$cdnItem = new CdnHash();
|
||||
$cdnItem->hash = $hash;
|
||||
$cdnItem->mime_type = $mime;
|
||||
$cdnItem->save();
|
||||
}
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
public static function Delete($hash)
|
||||
{
|
||||
$disk = self::GetDisk();
|
||||
|
||||
$cdnHash = CdnHash::where('hash', $hash);
|
||||
if($disk->exists($hash) && $cdnHash->exists()) {
|
||||
$cdnHash->delete();
|
||||
$disk->delete($hash);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function SaveContentB64($contentB64, $mime)
|
||||
{
|
||||
return self::SaveContent(base64_decode($contentB64), $mime);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2022
|
||||
Domain helper.
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class DomainHelper
|
||||
{
|
||||
public static function TopLevelDomain()
|
||||
{
|
||||
$baseurl = config('app.url');
|
||||
$baseurl = str_replace(['http://', 'https://'], '', $baseurl);
|
||||
|
||||
return $baseurl;
|
||||
}
|
||||
|
||||
public static function DotLeadTopLevelDomain()
|
||||
{
|
||||
return '.' . DomainHelper::TopLevelDomain();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Graphictoria 2022
|
||||
Error helper
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class ErrorHelper
|
||||
{
|
||||
/**
|
||||
* Returns a JSON array with the error code and message.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
private static function error($data, $code = 400)
|
||||
{
|
||||
return response(['errors' => [$data]], 400);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,200 +1,36 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2022
|
||||
Graphictoria 2022
|
||||
Grid helper
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Models\DynamicWebConfiguration;
|
||||
use App\Helpers\COMHelper;
|
||||
use App\Models\WebsiteConfiguration;
|
||||
|
||||
class GridHelper
|
||||
{
|
||||
public static function isIpWhitelisted()
|
||||
{
|
||||
$ip = request()->ip();
|
||||
$whitelistedIps = explode(';', DynamicWebConfiguration::where('name', 'WhitelistedIPs')->first()->value);
|
||||
public static function isIpWhitelisted(Request $request) {
|
||||
$ip = $request->ip();
|
||||
$whitelistedIps = explode(';', WebsiteConfiguration::where('name', 'WhitelistedIPs')->first()->value);
|
||||
|
||||
return in_array($ip, $whitelistedIps);
|
||||
}
|
||||
|
||||
public static function isAccessKeyValid()
|
||||
{
|
||||
$accessKey = DynamicWebConfiguration::where('name', 'ComputeServiceAccessKey')->first()->value;
|
||||
public static function isAccessKeyValid(Request $request) {
|
||||
$accessKey = WebsiteConfiguration::where('name', 'ComputeServiceAccessKey')->first()->value;
|
||||
|
||||
return (request()->header('AccessKey') == $accessKey);
|
||||
return ($request->header('AccessKey') == $accessKey);
|
||||
}
|
||||
|
||||
public static function hasAllAccess()
|
||||
{
|
||||
if(app()->runningInConsole()) return true;
|
||||
if(self::isIpWhitelisted() && self::isAccessKeyValid()) return true;
|
||||
public static function hasAllAccess(Request $request) {
|
||||
if(COMHelper::isCOM()) return true;
|
||||
if(GridHelper::isIpWhitelisted($request) && GridHelper::isAccessKeyValid($request)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function LuaValue($value)
|
||||
{
|
||||
switch ($value) {
|
||||
case is_bool(json_encode($value)) || $value == 1:
|
||||
return json_encode($value);
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
public static function CastType($value)
|
||||
{
|
||||
$luaTypeConversions = [
|
||||
'NULL' => 'LUA_TNIL',
|
||||
'boolean' => 'LUA_TBOOLEAN',
|
||||
'integer' => 'LUA_TNUMBER',
|
||||
'double' => 'LUA_TNUMBER',
|
||||
'string' => 'LUA_TSTRING',
|
||||
'array' => 'LUA_TTABLE',
|
||||
'object' => 'LUA_TNIL'
|
||||
];
|
||||
return $luaTypeConversions[gettype($value)];
|
||||
}
|
||||
|
||||
public static function ToLuaArguments($luaArguments = [])
|
||||
{
|
||||
$luaValue = ['LuaValue' => []];
|
||||
|
||||
foreach ($luaArguments as $argument) {
|
||||
array_push(
|
||||
$luaValue['LuaValue'],
|
||||
[
|
||||
'type' => self::CastType($argument),
|
||||
'value' => self::LuaValue($argument)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return $luaValue;
|
||||
}
|
||||
|
||||
public static function Job($jobID, $expiration, $category, $cores, $scriptName, $script, $scriptArgs = [])
|
||||
{
|
||||
return [
|
||||
'job' => [
|
||||
'id' => $jobID,
|
||||
'expirationInSeconds' => $expiration,
|
||||
'category' => $category,
|
||||
'cores' => $cores
|
||||
],
|
||||
'script' => [
|
||||
'name' => $scriptName,
|
||||
'script' => $script,
|
||||
'arguments' => self::ToLuaArguments($scriptArgs)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public static function JobTemplate($jobID, $expiration, $category, $cores, $scriptName, $templateName, $scriptArgs = [])
|
||||
{
|
||||
$disk = Storage::build([
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/grid/scripts'),
|
||||
]);
|
||||
|
||||
$fileName = sprintf('%s.lua', $templateName);
|
||||
|
||||
if(!$disk->exists($fileName))
|
||||
throw new Exception('Unable to locate template file.');
|
||||
|
||||
$job = self::Job($jobID, $expiration, $category, $cores, $scriptName, '', $scriptArgs);
|
||||
$job['script']['script'] = $disk->get($fileName);
|
||||
|
||||
return $job;
|
||||
}
|
||||
|
||||
private static function getThumbDisk()
|
||||
{
|
||||
return Storage::build([
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/grid/thumbnails'),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getDefaultThumbnail($fileName)
|
||||
{
|
||||
$disk = self::getThumbDisk();
|
||||
|
||||
if(!$disk->exists($fileName))
|
||||
throw new Exception('Unable to locate template file.');
|
||||
|
||||
return $disk->get($fileName);
|
||||
}
|
||||
|
||||
public static function getUnknownThumbnail()
|
||||
{
|
||||
return self::getDefaultThumbnail('UnknownThumbnail.png');
|
||||
}
|
||||
|
||||
private static function getGameDisk()
|
||||
{
|
||||
return Storage::build([
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/grid/game'),
|
||||
]);
|
||||
}
|
||||
|
||||
private static function getXMLFromGameDisk($fileName)
|
||||
{
|
||||
$disk = self::getGameDisk();
|
||||
|
||||
if(!$disk->exists($fileName))
|
||||
throw new Exception('Unable to locate template file.');
|
||||
|
||||
return $disk->get($fileName);
|
||||
}
|
||||
|
||||
public static function getBodyColorsXML()
|
||||
{
|
||||
return self::getXMLFromGameDisk('BodyColors.xml');
|
||||
}
|
||||
|
||||
public static function getBodyPartXML()
|
||||
{
|
||||
return self::getXMLFromGameDisk('BodyPart.xml');
|
||||
}
|
||||
|
||||
public static function getFaceXML()
|
||||
{
|
||||
return self::getXMLFromGameDisk('Face.xml');
|
||||
}
|
||||
|
||||
public static function getArbiter($name)
|
||||
{
|
||||
$query = DynamicWebConfiguration::where('name', sprintf('%sArbiterIP', $name))->first();
|
||||
if(!$query)
|
||||
throw new Exception('Unknown arbiter.');
|
||||
|
||||
return $query->value;
|
||||
}
|
||||
|
||||
public static function gameArbiter()
|
||||
{
|
||||
return sprintf('http://%s:64989', self::getArbiter('Game'));
|
||||
}
|
||||
|
||||
public static function thumbnailArbiter()
|
||||
{
|
||||
return sprintf('http://%s:64989', self::getArbiter('Thumbnail'));
|
||||
}
|
||||
|
||||
public static function gameArbiterMonitor()
|
||||
{
|
||||
return sprintf('http://%s:64990', self::getArbiter('Game'));
|
||||
}
|
||||
|
||||
public static function thumbnailArbiterMonitor()
|
||||
{
|
||||
return sprintf('http://%s:64990', self::getArbiter('Thumbnail'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Graphictoria 2022
|
||||
JSON Pretty Printer
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class JSON
|
||||
{
|
||||
public static function EncodeResponse($array) {
|
||||
$json = json_encode(
|
||||
$array,
|
||||
JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS
|
||||
);
|
||||
|
||||
return response($json)
|
||||
->header('Content-Type', 'application/json');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2022
|
||||
Maintenance helper
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Foundation\Http\MaintenanceModeBypassCookie;
|
||||
|
||||
class MaintenanceHelper
|
||||
{
|
||||
public static function isDown()
|
||||
{
|
||||
if(GridHelper::isIpWhitelisted())
|
||||
return false;
|
||||
|
||||
if(!file_exists(storage_path('framework/down')))
|
||||
return false;
|
||||
|
||||
$data = json_decode(file_get_contents(storage_path('framework/down')), true);
|
||||
|
||||
return (app()->isDownForMaintenance() && !MaintenanceHelper::hasValidBypassCookie($data));
|
||||
}
|
||||
|
||||
protected static function hasValidBypassCookie(array $data)
|
||||
{
|
||||
$request = request();
|
||||
|
||||
return isset($data['secret']) &&
|
||||
$request->cookie('vb_constraint') &&
|
||||
MaintenanceModeBypassCookie::isValid(
|
||||
$request->cookie('vb_constraint'),
|
||||
$data['secret']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2022
|
||||
A bit of a hacky way to implement markdown with laravel.
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Support\HtmlString;
|
||||
use League\CommonMark\Environment\Environment;
|
||||
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
||||
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
|
||||
use League\CommonMark\Extension\CommonMark\Node\Inline\Image;
|
||||
use League\CommonMark\Extension\DefaultAttributes\DefaultAttributesExtension;
|
||||
use League\CommonMark\Extension\Table\TableExtension;
|
||||
use League\CommonMark\MarkdownConverter;
|
||||
|
||||
class MarkdownHelper
|
||||
{
|
||||
// TODO: XlXi: Add a non-nav alert mode for links.
|
||||
// XlXi: This bit was partially taken from https://github.com/laravel/framework/blob/b9203fca96960ef9cd8860cb4ec99d1279353a8d/src/Illuminate/Mail/Markdown.php line 106
|
||||
public static function parse($text) {
|
||||
$environment = new Environment([
|
||||
'default_attributes' => [
|
||||
Link::class => [
|
||||
'class' => ['text-decoration-none']
|
||||
],
|
||||
Image::class => [
|
||||
'classes' => ['img-fluid']
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$environment->addExtension(new CommonMarkCoreExtension);
|
||||
$environment->addExtension(new TableExtension);
|
||||
$environment->addExtension(new DefaultAttributesExtension);
|
||||
|
||||
$converter = new MarkdownConverter($environment);
|
||||
|
||||
return new HtmlString($converter->convert($text)->getContent());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2022
|
||||
Number helper.
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class NumberHelper
|
||||
{
|
||||
public static function Abbreviate($number)
|
||||
{
|
||||
$divisors = array(
|
||||
pow(1000, 0) => '', // 1000^0 == 1
|
||||
pow(1000, 1) => 'K+', // Thousand
|
||||
pow(1000, 2) => 'M+', // Million
|
||||
pow(1000, 3) => 'B+', // Billion
|
||||
pow(1000, 4) => 'T+', // Trillion
|
||||
pow(1000, 5) => 'Qa+', // Quadrillion
|
||||
pow(1000, 6) => 'Qi+', // Quintillion
|
||||
);
|
||||
|
||||
foreach ($divisors as $divisor => $shorthand) {
|
||||
if (abs($number) < ($divisor * 1000))
|
||||
break;
|
||||
}
|
||||
|
||||
return number_format(floor($number / $divisor), 0) . $shorthand;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2022
|
||||
Quick Administration and Management Bar helper
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\UsageCounter;
|
||||
|
||||
class QAaMBHelper
|
||||
{
|
||||
public static function wmiWBemLocatorQuery($query)
|
||||
{
|
||||
if(class_exists('\\COM')) {
|
||||
try {
|
||||
$WbemLocator = new \COM( "WbemScripting.SWbemLocator" );
|
||||
$WbemServices = $WbemLocator->ConnectServer( '127.0.0.1', 'root\CIMV2' );
|
||||
$WbemServices->Security_->ImpersonationLevel = 3;
|
||||
return $WbemServices->ExecQuery( $query );
|
||||
} catch ( \com_exception $e ) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
} elseif ( ! extension_loaded( 'com_dotnet' ) )
|
||||
trigger_error( 'It seems that the COM is not enabled in your php.ini', E_USER_WARNING );
|
||||
else {
|
||||
$err = error_get_last();
|
||||
trigger_error( $err['message'], E_USER_WARNING );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getSystemMemoryInfo($output_key = '')
|
||||
{
|
||||
return cache()->remember('QAaMB-Memory-Info', 5, function(){
|
||||
$keys = array('MemTotal', 'MemFree', 'MemAvailable', 'SwapTotal', 'SwapFree');
|
||||
$result = array();
|
||||
|
||||
try {
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
|
||||
// LINUX
|
||||
|
||||
$proc_dir = '/proc/';
|
||||
$data = _dir_in_allowed_path( $proc_dir ) ? @file( $proc_dir . 'meminfo' ) : false;
|
||||
if ( is_array( $data ) )
|
||||
foreach ( $data as $d ) {
|
||||
if ( 0 == strlen( trim( $d ) ) )
|
||||
continue;
|
||||
$d = preg_split( '/:/', $d );
|
||||
$key = trim( $d[0] );
|
||||
if ( ! in_array( $key, $keys ) )
|
||||
continue;
|
||||
$value = 1000 * floatval( trim( str_replace( ' kB', '', $d[1] ) ) );
|
||||
$result[$key] = $value;
|
||||
}
|
||||
} else {
|
||||
// WINDOWS
|
||||
|
||||
$wmi_found = false;
|
||||
if ( $wmi_query = self::wmiWBemLocatorQuery(
|
||||
"SELECT FreePhysicalMemory,FreeVirtualMemory,TotalSwapSpaceSize,TotalVirtualMemorySize,TotalVisibleMemorySize FROM Win32_OperatingSystem" ) ) {
|
||||
foreach($wmi_query as $r) {
|
||||
$result['MemFree'] = $r->FreePhysicalMemory * 1024;
|
||||
$result['MemAvailable'] = $r->FreeVirtualMemory * 1024;
|
||||
$result['SwapFree'] = $r->TotalSwapSpaceSize * 1024;
|
||||
$result['SwapTotal'] = $r->TotalVirtualMemorySize * 1024;
|
||||
$result['MemTotal'] = $r->TotalVisibleMemorySize * 1024;
|
||||
$wmi_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
return empty($output_key) || !isset($result[$output_key]) ? $result : $result[$output_key];
|
||||
});
|
||||
}
|
||||
|
||||
public static function getSystemCpuInfo($output_key = '')
|
||||
{
|
||||
$result = 0;
|
||||
|
||||
try {
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
|
||||
// LINUX
|
||||
|
||||
return sys_getloadavg();
|
||||
} else {
|
||||
// WINDOWS
|
||||
|
||||
$wmi_found = false;
|
||||
if ( $wmi_query = self::wmiWBemLocatorQuery(
|
||||
"SELECT LoadPercentage FROM Win32_Processor" ) ) {
|
||||
foreach($wmi_query as $r) {
|
||||
$result = $r->LoadPercentage / 100;
|
||||
$wmi_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
return empty($output_key) || !isset($result[$output_key]) ? $result : $result[$output_key];
|
||||
}
|
||||
|
||||
public static function memoryString($memory)
|
||||
{
|
||||
$unit = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
|
||||
return @round($memory/pow(1024,($i=floor(log($memory,1024)))),2).' '.$unit[$i];
|
||||
}
|
||||
|
||||
public static function getMemoryUsage()
|
||||
{
|
||||
$memoryInfo = json_decode(UsageCounter::where('name', 'Memory')->first()->value, true);
|
||||
|
||||
// XlXi: the -2 is required so it fits inside of the bar thing
|
||||
// XlXi: change this if theres ever a separate graph
|
||||
return sprintf(
|
||||
'%s of %s (%s%%) <br/> %s Free',
|
||||
self::memoryString($memoryInfo['MemTotal'] - $memoryInfo['MemFree']),
|
||||
self::memoryString($memoryInfo['MemTotal']),
|
||||
round(self::getMemoryPercentage() * (100-2)),
|
||||
self::memoryString($memoryInfo['MemFree'])
|
||||
);
|
||||
}
|
||||
|
||||
public static function getMemoryPercentage()
|
||||
{
|
||||
$memoryInfo = json_decode(UsageCounter::where('name', 'Memory')->first()->value, true);
|
||||
|
||||
return ($memoryInfo['MemTotal'] - $memoryInfo['MemFree']) / $memoryInfo['MemTotal'];
|
||||
}
|
||||
|
||||
public static function getCpuUsage()
|
||||
{
|
||||
$cpuInfo = UsageCounter::where('name', 'CPU')->first();
|
||||
|
||||
// XlXi: the -2 is required so it fits inside of the bar thing
|
||||
// XlXi: change this if theres ever a separate graph
|
||||
return sprintf(
|
||||
'%s%% CPU Usage',
|
||||
round(floatval($cpuInfo->value) * (100-2))
|
||||
);
|
||||
}
|
||||
|
||||
public static function getCpuPercentage()
|
||||
{
|
||||
$cpuInfo = UsageCounter::where('name', 'CPU')->first();
|
||||
|
||||
return $cpuInfo->value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Graphictoria 2022
|
||||
Random generator
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class Random
|
||||
{
|
||||
/**
|
||||
* Creates a random string of the specified length.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public static function Str($length) {
|
||||
// https://stackoverflow.com/questions/4356289/php-random-string-generator
|
||||
|
||||
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$charactersLength = strlen($characters);
|
||||
$randomString = '';
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$randomString .= $characters[rand(0, $charactersLength - 1)];
|
||||
}
|
||||
return $randomString;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
XlXi 2022
|
||||
Validation Helper
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
class ValidationHelper
|
||||
{
|
||||
public static function generateValidatorError($validator) {
|
||||
return response(self::generateErrorJSON($validator), 400);
|
||||
}
|
||||
|
||||
public static function generateErrorJSON(Validator $validator) {
|
||||
$errorModel = [
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
foreach($validator->errors()->all() as $error) {
|
||||
array_push($errorModel['errors'], ['code' => 400, 'message' => $error]);
|
||||
}
|
||||
|
||||
return $errorModel;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,353 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
use App\Helpers\AssetHelper;
|
||||
use App\Helpers\CdnHelper;
|
||||
use App\Helpers\GridHelper;
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\AppDeployment;
|
||||
use App\Models\AssetType;
|
||||
use App\Models\Deployment;
|
||||
use App\Models\RobloxAsset;
|
||||
use App\Rules\AppDeploymentFilenameRule;
|
||||
|
||||
class AdminController extends Controller
|
||||
{
|
||||
// Moderator+
|
||||
|
||||
|
||||
// Admin+
|
||||
function manualAssetUpload(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'asset-type-id' => ['required', 'int'],
|
||||
'name' => ['required', 'string'],
|
||||
'description' => ['string', 'nullable'],
|
||||
'roblox-id' => ['int', 'min:0', 'nullable'],
|
||||
'on-sale' => ['required', 'boolean'],
|
||||
'price' => ['required_if:on-sale,true', 'int', 'min:0'],
|
||||
'content' => ['nullable'],
|
||||
'mesh-id' => ['int', 'nullable'],
|
||||
'base-id' => ['int', 'nullable'],
|
||||
'overlay-id' => ['int', 'nullable'],
|
||||
],[
|
||||
'asset-type-id.required' => 'An asset type ID must be provided.',
|
||||
'roblox-id.integer' => 'Roblox ID must be an integer.'
|
||||
]);
|
||||
|
||||
if($validator->fails())
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
|
||||
$valid = $validator->valid();
|
||||
$isRobloxAsset = ($request->has('roblox-id') && $valid['roblox-id'] > 0);
|
||||
|
||||
if($isRobloxAsset)
|
||||
{
|
||||
$uploadedAsset = RobloxAsset::where('robloxAssetId', $valid['roblox-id'])->first();
|
||||
if($uploadedAsset)
|
||||
{
|
||||
$validator->errors()->add('roblox-id', 'This asset has already been uploaded!');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
}
|
||||
|
||||
$assetType = AssetType::where('id', $valid['asset-type-id'])
|
||||
->where('adminCreatable', 1)
|
||||
->first();
|
||||
if(!$assetType)
|
||||
{
|
||||
$validator->errors()->add('asset-type-id', 'Invalid asset type for admin upload.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$assetFunction = 'Unknown';
|
||||
$assetFunctionArgs = [];
|
||||
switch($assetType->id)
|
||||
{
|
||||
case 27: // Torso
|
||||
case 28: // Right Arm
|
||||
case 29: // Left Arm
|
||||
case 30: // Left Leg
|
||||
case 31: // Right Leg
|
||||
$assetFunctionArgs = [$assetType->id, $valid];
|
||||
$assetFunction = 'BodyPart';
|
||||
break;
|
||||
case 18: // Face
|
||||
$assetFunctionArgs = [$validator, $valid];
|
||||
$assetFunction = 'Face';
|
||||
break;
|
||||
default:
|
||||
$assetFunctionArgs = [$validator];
|
||||
$assetFunction = 'Generic';
|
||||
break;
|
||||
}
|
||||
|
||||
$assetContent = $this->{ 'manualAssetUpload' . $assetFunction }($request, ...$assetFunctionArgs);
|
||||
|
||||
$hash = CdnHelper::SaveContent($assetContent, 'application/octet-stream');
|
||||
$asset = AssetHelper::newAsset([
|
||||
'creatorId' => 1,
|
||||
'name' => $valid['name'],
|
||||
'description' => $valid['description'],
|
||||
'approved' => true,
|
||||
'priceInTokens' => $valid['price'],
|
||||
'onSale' => $valid['on-sale'] == 1 ? true : false,
|
||||
'assetTypeId' => $assetType->id,
|
||||
'assetVersionId' => 0
|
||||
], $hash);
|
||||
$asset->logAdminUpload(Auth::user()->id);
|
||||
|
||||
if($isRobloxAsset)
|
||||
{
|
||||
RobloxAsset::create([
|
||||
'robloxAssetId' => $valid['roblox-id'],
|
||||
'localAssetId' => $asset->id
|
||||
]);
|
||||
}
|
||||
|
||||
return response([
|
||||
'success' => true,
|
||||
'message' => 'Your asset has been successfully uploaded!',
|
||||
'assetId' => $asset->id
|
||||
]);
|
||||
}
|
||||
|
||||
function manualAssetUploadBodyPart(Request $request, $assetTypeId, $valid)
|
||||
{
|
||||
$bodyParts = [
|
||||
27 => 1, // Torso
|
||||
28 => 3, // Right Arm
|
||||
29 => 2, // Left Arm
|
||||
30 => 4, // Left Leg
|
||||
31 => 5 // Right Leg
|
||||
];
|
||||
|
||||
$document = simplexml_load_string(GridHelper::getBodyPartXML());
|
||||
$document->xpath('//int[@name="BaseTextureId"]')[0][0] = $valid['base-id'] ?: 0;
|
||||
$document->xpath('//token[@name="BodyPart"]')[0][0] = $bodyParts[$assetTypeId];
|
||||
$document->xpath('//int[@name="MeshId"]')[0][0] = $valid['mesh-id'];
|
||||
$document->xpath('//string[@name="Name"]')[0][0] = $valid['name'];
|
||||
$document->xpath('//int[@name="OverlayTextureId"]')[0][0] = $valid['overlay-id'] ?: 0;
|
||||
|
||||
$domXML = dom_import_simplexml($document);
|
||||
$assetContent = $domXML->ownerDocument->saveXML($domXML->ownerDocument->documentElement);
|
||||
|
||||
return $assetContent;
|
||||
}
|
||||
|
||||
function manualAssetUploadFace(Request $request, $validator, $valid)
|
||||
{
|
||||
if(!$request->has('content'))
|
||||
{
|
||||
$validator->errors()->add('content', 'Asset content cannot be blank!');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$hash = CdnHelper::SaveContent(
|
||||
file_get_contents($request->file('content')->path()),
|
||||
'application/octet-stream'
|
||||
);
|
||||
$imageAsset = AssetHelper::newAsset([
|
||||
'creatorId' => 1,
|
||||
'name' => $valid['name'],
|
||||
'approved' => true,
|
||||
'onSale' => false,
|
||||
'assetTypeId' => 1, // Image
|
||||
'assetVersionId' => 0
|
||||
], $hash);
|
||||
$imageAsset->logAdminUpload(Auth::user()->id);
|
||||
$imageAssetUrl = route('client.asset', ['id' => $imageAsset->id]);
|
||||
|
||||
$document = simplexml_load_string(GridHelper::getFaceXML());
|
||||
$document->xpath('//Content[@name="Texture"]')[0][0]->addChild('url', $imageAssetUrl);
|
||||
|
||||
$domXML = dom_import_simplexml($document);
|
||||
$assetContent = $domXML->ownerDocument->saveXML($domXML->ownerDocument->documentElement);
|
||||
|
||||
return $assetContent;
|
||||
}
|
||||
|
||||
function manualAssetUploadGeneric(Request $request, $validator)
|
||||
{
|
||||
if(!$request->has('content'))
|
||||
{
|
||||
$validator->errors()->add('content', 'Asset content cannot be blank!');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$assetContent = file_get_contents($request->file('content')->path());
|
||||
|
||||
return $assetContent;
|
||||
}
|
||||
|
||||
function manualAssetUploadUnknown(Request $request)
|
||||
{
|
||||
throw new \BadMethodCallException('Not implemented');
|
||||
}
|
||||
|
||||
// Owner+
|
||||
function deploy(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'version' => ['regex:/version\\-[a-fA-F0-9]{16}/'],
|
||||
'type' => ['required_without:version', 'regex:/(Deploy|Revert)/i'],
|
||||
'app' => ['required_without:version', 'regex:/(Client|Studio)/i']
|
||||
]);
|
||||
|
||||
if($validator->fails())
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
$response = [
|
||||
'status' => 'Loading',
|
||||
'version' => null,
|
||||
'message' => 'Please wait...',
|
||||
'progress' => 0
|
||||
];
|
||||
|
||||
if(!$request->has('version'))
|
||||
{
|
||||
$deployment = Deployment::newVersionHash($valid);
|
||||
|
||||
$response['version'] = $deployment->version;
|
||||
$response['message'] = 'Created deployment.';
|
||||
$response['progress'] = 0;
|
||||
|
||||
return response($response);
|
||||
}
|
||||
|
||||
$deployment = Deployment::where('version', $valid['version'])->first();
|
||||
if($deployment === null || !$deployment->isValid()) {
|
||||
$validator->errors()->add('version', 'Unknown version deployment hash.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$response['version'] = $deployment->version;
|
||||
|
||||
if($deployment->error != null)
|
||||
{
|
||||
$response['status'] = 'Error';
|
||||
$response['message'] = sprintf('Failed to deploy %s. Error: %s', $deployment->version, $deployment->error);
|
||||
$response['progress'] = 1;
|
||||
return response($response);
|
||||
}
|
||||
|
||||
$steps = 5;
|
||||
$response['progress'] = $deployment->step/$steps;
|
||||
switch($deployment->step)
|
||||
{
|
||||
case 0:
|
||||
$response['message'] = 'Files uploading.';
|
||||
break;
|
||||
case 1:
|
||||
$response['message'] = 'Batching deployment.';
|
||||
break;
|
||||
case 2:
|
||||
$response['message'] = 'Unpacking files.';
|
||||
break;
|
||||
case 3:
|
||||
$response['message'] = 'Updating version security.';
|
||||
break;
|
||||
case 4:
|
||||
$response['message'] = 'Pushing deployment to setup.';
|
||||
break;
|
||||
case 5:
|
||||
$response['status'] = 'Success';
|
||||
$response['message'] = sprintf('Deploy completed. Successfully deployed %s %s', $deployment->app, $deployment->version);
|
||||
break;
|
||||
}
|
||||
|
||||
return response($response);
|
||||
}
|
||||
|
||||
function deployVersion(Request $request, string $version)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'file.*' => ['required']
|
||||
]);
|
||||
|
||||
if($validator->fails())
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
$deployment = Deployment::where('version', $version)->first();
|
||||
if($deployment === null || !$deployment->isValid() || $deployment->step != 0) {
|
||||
$validator->errors()->add('version', 'Unknown version deployment hash.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$deploymentRule = new AppDeploymentFilenameRule($deployment->app);
|
||||
if(!$deploymentRule->passes('file', $request->file('file')))
|
||||
{
|
||||
$deployment->error = 'Missing files.';
|
||||
$deployment->save();
|
||||
|
||||
$validator->errors()->add('file', $deployment->error);
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
foreach($request->file('file') as $file)
|
||||
{
|
||||
$file->storeAs(
|
||||
'setuptmp',
|
||||
sprintf('%s-%s', $version, $file->getClientOriginalName())
|
||||
);
|
||||
}
|
||||
|
||||
$deployment->step = 1; // Batching deployment.
|
||||
$deployment->save();
|
||||
|
||||
AppDeployment::dispatch($deployment);
|
||||
}
|
||||
|
||||
// RCC Only
|
||||
function uploadRobloxAsset(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'contentId' => ['required', 'int']
|
||||
]);
|
||||
|
||||
if($validator->fails())
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
|
||||
if(!GridHelper::hasAllAccess())
|
||||
{
|
||||
$validator->errors()->add('contentId', 'This API can only be called by the web service.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
$asset = AssetHelper::uploadRobloxAsset($valid['contentId'], true);
|
||||
|
||||
return route('client.asset', ['id' => $asset->id]);
|
||||
}
|
||||
|
||||
function uploadAsset(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'contentId' => ['required', 'int']
|
||||
]);
|
||||
|
||||
if($validator->fails())
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
|
||||
if(!GridHelper::hasAllAccess())
|
||||
{
|
||||
$validator->errors()->add('contentId', 'This API can only be called by the web service.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
$asset = AssetHelper::uploadCustomRobloxAsset($valid['contentId'], true, base64_encode($request->getContent()));
|
||||
|
||||
return route('client.asset', ['id' => $asset->id]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ApiController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
// 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');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,259 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\Helpers\BrickColorHelper;
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\AvatarAsset;
|
||||
use App\Models\AvatarColor;
|
||||
use App\Models\UserAsset;
|
||||
|
||||
class AvatarController extends Controller
|
||||
{
|
||||
protected $validAssetTypeIds = [
|
||||
'17', // Heads
|
||||
'18', // Faces
|
||||
'8', // Hats
|
||||
'2', // T-Shirts
|
||||
'11', // Shirts
|
||||
'12', // Pants
|
||||
'19', // Gear
|
||||
'27', // Torsos
|
||||
'29', // Left Arms
|
||||
'28', // Right Arms
|
||||
'30', // Left Legs
|
||||
'31', // Right Legs
|
||||
'32' // Packages
|
||||
];
|
||||
|
||||
public function redrawUser()
|
||||
{
|
||||
Auth::user()->redraw();
|
||||
|
||||
return response(['success' => true]);
|
||||
}
|
||||
|
||||
public static function GetUserAssets($userId)
|
||||
{
|
||||
return UserAsset::where('owner_id', $userId)
|
||||
->whereRelation('asset', 'moderated', false)
|
||||
->orderByDesc('id');
|
||||
}
|
||||
|
||||
public function listAssets(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'assetTypeId' => ['required', 'int']
|
||||
]);
|
||||
|
||||
if($validator->fails()) {
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
if(!in_array($valid['assetTypeId'], $this->validAssetTypeIds)) {
|
||||
$validator->errors()->add('assetTypeId', 'Invalid assetTypeId supplied.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$userAssets = self::GetUserAssets(Auth::user()->id)
|
||||
->whereRelation('asset', 'assetTypeId', $valid['assetTypeId'])
|
||||
->groupBy('asset_id')
|
||||
->paginate(12);
|
||||
$data = [];
|
||||
|
||||
foreach($userAssets as $userAsset)
|
||||
{
|
||||
$asset = $userAsset->asset;
|
||||
|
||||
array_push($data, [
|
||||
'id' => $asset->id,
|
||||
'Url' => $asset->getShopUrl(),
|
||||
'Thumbnail' => $asset->getThumbnail(),
|
||||
'Name' => $asset->name,
|
||||
'Wearing' => Auth::user()->isWearing($asset->id)
|
||||
]);
|
||||
}
|
||||
|
||||
return response([
|
||||
'data' => $data,
|
||||
'pages' => ($userAssets->hasPages() ? $userAssets->lastPage() : 1)
|
||||
]);
|
||||
}
|
||||
|
||||
public function listWearing(Request $request)
|
||||
{
|
||||
$avatarAssets = AvatarAsset::where('owner_id', Auth::user()->id)->get();
|
||||
$data = [];
|
||||
|
||||
foreach($avatarAssets as $avatarAsset)
|
||||
{
|
||||
$asset = $avatarAsset->asset;
|
||||
|
||||
array_push($data, [
|
||||
'id' => $asset->id,
|
||||
'Url' => $asset->getShopUrl(),
|
||||
'Thumbnail' => $asset->getThumbnail(),
|
||||
'Name' => $asset->name,
|
||||
'Wearing' => true
|
||||
]);
|
||||
}
|
||||
|
||||
return response([
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
public function wearAsset(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'id' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\Asset', 'id')->where(function($query) {
|
||||
return $query->where('moderated', false);
|
||||
})
|
||||
]
|
||||
]);
|
||||
|
||||
if($validator->fails()) {
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
$userAsset = self::GetUserAssets(Auth::user()->id)
|
||||
->where('asset_id', $valid['id'])
|
||||
->first();
|
||||
|
||||
if(!$userAsset) {
|
||||
$validator->errors()->add('id', 'User does not own asset.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
if(Auth::user()->isWearing($valid['id']) && $userAsset->asset->assetTypeId == 8) { // 8 = hat
|
||||
$validator->errors()->add('id', 'User is already wearing asset.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
if(!in_array($userAsset->asset->assetTypeId, $this->validAssetTypeIds)) {
|
||||
$validator->errors()->add('id', 'This asset cannot be worn.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$wornItems = AvatarAsset::where('owner_id', Auth::user()->id)
|
||||
->whereRelation('asset', 'assetTypeId', $userAsset->asset->assetTypeId);
|
||||
if($userAsset->asset->assetTypeId != 8 && $wornItems->exists()) // 8 = hat
|
||||
{
|
||||
$wornItems->delete();
|
||||
}
|
||||
elseif($userAsset->asset->assetTypeId == 8 && $wornItems->count() >= 10)
|
||||
{
|
||||
$validator->errors()->add('id', 'User has hit the wearing limit on this asset type.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
Auth::user()->wearAsset($valid['id']);
|
||||
Auth::user()->redraw();
|
||||
|
||||
return response(['success' => true]);
|
||||
}
|
||||
|
||||
public function removeAsset(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'id' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\Asset', 'id')->where(function($query) {
|
||||
return $query->where('moderated', false);
|
||||
})
|
||||
]
|
||||
]);
|
||||
|
||||
if($validator->fails()) {
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
if(!Auth::user()->isWearing($valid['id'])) {
|
||||
$validator->errors()->add('id', 'User is not wearing asset.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
AvatarAsset::where('owner_id', Auth::user()->id)
|
||||
->where('asset_id', $valid['id'])
|
||||
->delete();
|
||||
|
||||
Auth::user()->redraw();
|
||||
|
||||
return response(['success' => true]);
|
||||
}
|
||||
|
||||
public function setBodyColor(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'part' => ['required', 'regex:/(Head|Torso|LeftArm|RightArm|LeftLeg|RightLeg)/i'],
|
||||
'color' => ['required', 'int']
|
||||
]);
|
||||
|
||||
if($validator->fails()) {
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
if(!BrickColorHelper::isValidColor($valid['color'])) {
|
||||
$validator->errors()->add('color', 'Invalid color id.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$part = strtolower($valid['part']);
|
||||
switch($part)
|
||||
{
|
||||
case 'leftarm':
|
||||
$part = 'leftArm';
|
||||
break;
|
||||
case 'rightarm':
|
||||
$part = 'rightArm';
|
||||
break;
|
||||
case 'leftleg':
|
||||
$part = 'leftLeg';
|
||||
break;
|
||||
case 'rightleg':
|
||||
$part = 'rightLeg';
|
||||
break;
|
||||
}
|
||||
|
||||
$bodyColors = Auth::user()->getBodyColors();
|
||||
$bodyColors->{$part} = $valid['color'];
|
||||
$bodyColors->save();
|
||||
|
||||
Auth::user()->redraw();
|
||||
|
||||
return response(['success' => true]);
|
||||
}
|
||||
|
||||
public function getBodyColors(Request $request)
|
||||
{
|
||||
$bodyColors = Auth::user()->getBodyColors();
|
||||
|
||||
return response([
|
||||
'data' => [
|
||||
'Head' => $bodyColors->head,
|
||||
'Torso' => $bodyColors->torso,
|
||||
'RightArm' => $bodyColors->rightArm,
|
||||
'LeftArm' => $bodyColors->leftArm,
|
||||
'RightLeg' => $bodyColors->rightLeg,
|
||||
'LeftLeg' => $bodyColors->leftLeg
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\NegotiationTicket;
|
||||
|
||||
class ClientController extends Controller
|
||||
{
|
||||
function generateAuthTicket()
|
||||
{
|
||||
$ticket = Str::random(100);
|
||||
|
||||
NegotiationTicket::create([
|
||||
'ticket' => $ticket,
|
||||
'userId' => Auth::user()->id
|
||||
]);
|
||||
|
||||
return response($ticket)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Carbon\Carbon;
|
||||
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Comment;
|
||||
|
||||
class CommentsController extends Controller
|
||||
{
|
||||
protected function listJson(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'assetId' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\Asset', 'id')->where(function($query) {
|
||||
return $query->where('moderated', false);
|
||||
})
|
||||
]
|
||||
]);
|
||||
|
||||
if($validator->fails())
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
$comments = Comment::where('asset_id', $valid['assetId'])
|
||||
->where('deleted', false)
|
||||
->orderByDesc('id')
|
||||
->cursorPaginate(15);
|
||||
|
||||
$prevCursor = $comments->previousCursor();
|
||||
$nextCursor = $comments->nextCursor();
|
||||
|
||||
$result = [
|
||||
'data' => [],
|
||||
'prev_cursor' => ($prevCursor ? $prevCursor->encode() : null),
|
||||
'next_cursor' => ($nextCursor ? $nextCursor->encode() : null)
|
||||
];
|
||||
|
||||
foreach($comments as $comment) {
|
||||
$poster = $comment->user->userToJson();
|
||||
|
||||
$postDate = $comment['updated_at'];
|
||||
if(Carbon::now()->greaterThan($postDate->copy()->addDays(2)))
|
||||
$postDate = $postDate->isoFormat('lll');
|
||||
else
|
||||
$postDate = $postDate->calendar();
|
||||
|
||||
array_push($result['data'], [
|
||||
'commentId' => $comment->id,
|
||||
'poster' => $poster,
|
||||
'content' => $comment->content,
|
||||
'time' => $postDate
|
||||
]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function share(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'assetId' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\Asset', 'id')->where(function($query) {
|
||||
return $query->where('moderated', false);
|
||||
})
|
||||
],
|
||||
'content' => ['required', 'max:200']
|
||||
]);
|
||||
|
||||
if($validator->fails())
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
$comment = new Comment();
|
||||
$comment->asset_id = $valid['assetId'];
|
||||
$comment->author_id = Auth::id();
|
||||
$comment->content = $valid['content'];
|
||||
$comment->save();
|
||||
|
||||
return response(['success' => true]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Friend;
|
||||
use App\Models\Shout;
|
||||
use App\Models\User;
|
||||
|
||||
class FeedController extends Controller
|
||||
{
|
||||
protected function listJson()
|
||||
{
|
||||
// TODO: XlXi: Group shouts.
|
||||
$postsQuery = Shout::getPosts()
|
||||
->orderByDesc('id')
|
||||
->cursorPaginate(15);
|
||||
|
||||
/* */
|
||||
|
||||
$prevCursor = $postsQuery->previousCursor();
|
||||
$nextCursor = $postsQuery->nextCursor();
|
||||
|
||||
$posts = [
|
||||
'data' => [],
|
||||
'prev_cursor' => ($prevCursor ? $prevCursor->encode() : null),
|
||||
'next_cursor' => ($nextCursor ? $nextCursor->encode() : null)
|
||||
];
|
||||
|
||||
foreach($postsQuery as $post) {
|
||||
// TODO: XlXi: groups
|
||||
|
||||
$poster = [];
|
||||
if($post['poster_type'] == 'user') {
|
||||
$user = User::where('id', $post['poster_id'])->first();
|
||||
$poster = $user->userToJson();
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
$postDate = $post['updated_at'];
|
||||
if(Carbon::now()->greaterThan($postDate->copy()->addDays(2)))
|
||||
$postDate = $postDate->isoFormat('lll');
|
||||
else
|
||||
$postDate = $postDate->calendar();
|
||||
|
||||
/* */
|
||||
|
||||
array_push($posts['data'], [
|
||||
'postId' => $post['id'],
|
||||
'poster' => $poster,
|
||||
'content' => $post['content'],
|
||||
'time' => $postDate
|
||||
]);
|
||||
}
|
||||
|
||||
return response($posts);
|
||||
}
|
||||
|
||||
protected function share(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'content' => ['required', 'max:200']
|
||||
]);
|
||||
|
||||
$shout = new Shout();
|
||||
$shout->poster_id = Auth::id();
|
||||
$shout->poster_type = 'user';
|
||||
$shout->content = $validated['content'];
|
||||
$shout->save();
|
||||
|
||||
return response(['success' => true]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Universe;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class GamesController extends Controller
|
||||
{
|
||||
protected static function getAssets()
|
||||
{
|
||||
// TODO: XlXi: sort also based on how many people are in open servers
|
||||
return Universe::where('public', true)
|
||||
->whereRelation('starterPlace', 'moderated', false)
|
||||
->join('assets', 'assets.id', '=', 'universes.startPlaceId')
|
||||
->orderBy('assets.created_at', 'desc')
|
||||
->orderBy('assets.visits', 'desc');
|
||||
}
|
||||
|
||||
protected function listJson(Request $request)
|
||||
{
|
||||
$assets = self::getAssets()->paginate(30);
|
||||
|
||||
$data = [];
|
||||
foreach($assets as $asset) {
|
||||
$asset = $asset->starterPlace;
|
||||
$creator = $asset->user;
|
||||
|
||||
array_push($data, [
|
||||
'Name' => $asset->universe->name,
|
||||
'Creator' => [
|
||||
'Name' => $creator->username,
|
||||
'Url' => $creator->getProfileUrl()
|
||||
],
|
||||
'Playing' => 0,
|
||||
'Ratio' => 0,
|
||||
'Url' => route('games.asset', ['asset' => $asset->id, 'assetName' => Str::slug($asset->name, '-')])
|
||||
]);
|
||||
}
|
||||
|
||||
return response([
|
||||
'pages' => ($assets->hasPages() ? $assets->lastPage() : 1),
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
<?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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Transaction;
|
||||
use App\Models\TransactionType;
|
||||
use App\Models\User;
|
||||
|
||||
class MoneyController extends Controller
|
||||
{
|
||||
public function userSummary(Request $request)
|
||||
{
|
||||
$result = [
|
||||
'columns' => [],
|
||||
'total' => 0
|
||||
];
|
||||
|
||||
$dataPoints = [
|
||||
[
|
||||
'Name' => 'Item Purchases',
|
||||
'Points' => ['Purchases']
|
||||
],
|
||||
[
|
||||
'Name' => 'Sale of Goods',
|
||||
'Points' => ['Sales', 'Commissions']
|
||||
],
|
||||
[
|
||||
'Name' => 'Group Payouts',
|
||||
'Points' => ['Group Payouts']
|
||||
]
|
||||
];
|
||||
|
||||
foreach($dataPoints as $dataPoint)
|
||||
{
|
||||
$newColumn = ['name' => $dataPoint['Name'], 'total' => 0];
|
||||
|
||||
foreach($dataPoint['Points'] as $transactionType)
|
||||
{
|
||||
$column = $transactionType == 'Sales' ? 'seller_id' : 'user_id';
|
||||
|
||||
$newColumn['total'] += Transaction::where($column, Auth::user()->id)
|
||||
->where('transaction_type_id', TransactionType::IDFromType($transactionType))
|
||||
->where(function($query) use($request) {
|
||||
if(!$request->has('filter'))
|
||||
return $query;
|
||||
|
||||
$now = Carbon::now();
|
||||
switch($request->get('filter'))
|
||||
{
|
||||
case 'pastday':
|
||||
return $query->where('created_at', '>', $now->subDay());
|
||||
case 'pastweek':
|
||||
return $query->where('created_at', '>', $now->subWeek());
|
||||
case 'pastmonth':
|
||||
return $query->where('created_at', '>', $now->subMonth());
|
||||
case 'pastyear':
|
||||
return $query->where('created_at', '>', $now->subYear());
|
||||
default:
|
||||
return $query;
|
||||
}
|
||||
})
|
||||
->sum('delta');
|
||||
}
|
||||
|
||||
array_push($result['columns'], $newColumn);
|
||||
$result['total'] += $newColumn['total'];
|
||||
}
|
||||
|
||||
return response($result);
|
||||
}
|
||||
|
||||
public function userTransactions(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'filter' => ['required', 'in:purchases,sales,commissions,grouppayouts']
|
||||
]);
|
||||
|
||||
if($validator->fails())
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
$resultData = [];
|
||||
$transactionType = 0;
|
||||
switch($valid['filter'])
|
||||
{
|
||||
case 'purchases':
|
||||
$transactionType = TransactionType::where('name', 'Purchases')->first();
|
||||
break;
|
||||
case 'sales':
|
||||
$transactionType = TransactionType::where('name', 'Sales')->first();
|
||||
break;
|
||||
case 'commissions':
|
||||
$transactionType = TransactionType::where('name', 'Commissions')->first();
|
||||
break;
|
||||
case 'grouppayouts':
|
||||
$transactionType = TransactionType::where('name', 'Group Payouts')->first();
|
||||
break;
|
||||
}
|
||||
|
||||
$transactions = Transaction::where(function($query) use($valid) {
|
||||
if($valid['filter'] == 'sales')
|
||||
return $query->where('seller_id', Auth::user()->id);
|
||||
return $query->where('user_id', Auth::user()->id);
|
||||
})
|
||||
->where('transaction_type_id', $transactionType->id)
|
||||
->with('asset')
|
||||
->orderByDesc('id')
|
||||
->cursorPaginate(30);
|
||||
$prevCursor = $transactions->previousCursor();
|
||||
$nextCursor = $transactions->nextCursor();
|
||||
|
||||
foreach($transactions as $transaction)
|
||||
{
|
||||
$user = null;
|
||||
if($valid['filter'] != 'sales')
|
||||
$user = $transaction->seller;
|
||||
else
|
||||
$user = $transaction->user;
|
||||
|
||||
$asset = null;
|
||||
if($transactionType->format != '')
|
||||
$asset = [
|
||||
'url' => $transaction->asset->getShopUrl(),
|
||||
'name' => $transaction->asset->name
|
||||
];
|
||||
|
||||
array_push($resultData, [
|
||||
'date' => $transaction->created_at->isoFormat('lll'),
|
||||
'member' => $user->userToJson(),
|
||||
'description' => $transactionType->format,
|
||||
'amount' => $transaction->delta,
|
||||
'item' => $asset
|
||||
]);
|
||||
}
|
||||
|
||||
return response([
|
||||
'data' => $resultData,
|
||||
'prev_cursor' => ($prevCursor ? $prevCursor->encode() : null),
|
||||
'next_cursor' => ($nextCursor ? $nextCursor->encode() : null)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Transaction;
|
||||
use App\Models\TransactionType;
|
||||
use App\Models\UserAsset;
|
||||
|
||||
class ShopController extends Controller
|
||||
{
|
||||
protected $validAssetTypeIds = [
|
||||
'2', // T-Shirts
|
||||
'8', // Hats
|
||||
'11', // Shirts
|
||||
'12', // Pants
|
||||
'17', // Heads
|
||||
'18', // Faces
|
||||
'19', // Gear
|
||||
'32' // Packages
|
||||
];
|
||||
|
||||
protected static function getAssets($assetTypeIds, $gearGenre=null)
|
||||
{
|
||||
// TODO: XlXi: Group owned assets
|
||||
return Asset::where('approved', true)
|
||||
->where('moderated', false)
|
||||
->where('onSale', true)
|
||||
->where(function($query) use($assetTypeIds, $gearGenre) {
|
||||
$query->whereIn('assetTypeId', explode(',', $assetTypeIds));
|
||||
|
||||
if ($gearGenre != null)
|
||||
$query->whereIn('assetAttributeId', explode(',', $gearGenre));
|
||||
});
|
||||
}
|
||||
|
||||
protected function listJson(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'assetTypeId' => ['required', 'regex:/^\\d(,?\\d)*$/i'],
|
||||
'gearGenreId' => ['regex:/^\\d(,?\\d)*$/i']
|
||||
]);
|
||||
|
||||
if($validator->fails()) {
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
foreach(explode(',', $valid['assetTypeId']) as $assetTypeId) {
|
||||
if(!in_array($assetTypeId, $this->validAssetTypeIds)) {
|
||||
$validator->errors()->add('assetTypeId', 'Invalid assetTypeId supplied.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
}
|
||||
|
||||
if($valid['assetTypeId'] != '19' && isset($valid['gearGenreId'])) {
|
||||
$validator->errors()->add('gearGenreId', 'gearGenreId can only be used with assetTypeId 19.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
$assets = self::getAssets($valid['assetTypeId'], (isset($valid['gearGenreId']) ? $valid['gearGenreId'] : null));
|
||||
$assets = $assets->orderByDesc('created_at')
|
||||
->paginate(35);
|
||||
|
||||
$data = [];
|
||||
foreach($assets as $asset) {
|
||||
$creator = $asset->user;
|
||||
|
||||
array_push($data, [
|
||||
'Name' => $asset->name,
|
||||
'Creator' => [
|
||||
'Name' => $creator->username,
|
||||
'Url' => $creator->getProfileUrl()
|
||||
],
|
||||
'Thumbnail' => $asset->getThumbnail(),
|
||||
'OnSale' => $asset->onSale,
|
||||
'Price' => $asset->priceInTokens,
|
||||
'Url' => $asset->getShopUrl()
|
||||
]);
|
||||
}
|
||||
|
||||
return response([
|
||||
'pages' => ($assets->hasPages() ? $assets->lastPage() : 1),
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
protected function purchase(Request $request, Asset $asset)
|
||||
{
|
||||
// TODO: XlXi: limiteds
|
||||
$validator = Validator::make($request->all(), [
|
||||
'expectedPrice' => ['int']
|
||||
]);
|
||||
|
||||
if($validator->fails()) {
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
$result = [
|
||||
'success' => false,
|
||||
'userFacingMessage' => null,
|
||||
'priceInTokens' => $asset->priceInTokens
|
||||
];
|
||||
$price = $asset->priceInTokens;
|
||||
$user = Auth::user();
|
||||
|
||||
if($asset->assetType->locked)
|
||||
{
|
||||
$result['userFacingMessage'] = 'This asset cannot be purchased.';
|
||||
$result['priceInTokens'] = null;
|
||||
return response($result);
|
||||
}
|
||||
|
||||
if($user->hasAsset($asset->id))
|
||||
{
|
||||
$result['userFacingMessage'] = 'You already own this item.';
|
||||
return response($result);
|
||||
}
|
||||
|
||||
if($valid['expectedPrice'] != $price)
|
||||
return response($result);
|
||||
|
||||
if($asset->priceInTokens > $user->tokens)
|
||||
{
|
||||
$result['userFacingMessage'] = 'You can\'t afford this item.';
|
||||
return response($result);
|
||||
}
|
||||
|
||||
$result['success'] = true;
|
||||
|
||||
Transaction::createAssetSale($user, $asset);
|
||||
$user->removeFunds($price);
|
||||
$asset->user->addFunds($price * (1-.3)); // XlXi: 30% tax
|
||||
UserAsset::createSerialed($user->id, $asset->id);
|
||||
|
||||
return response($result);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Helpers\GridHelper;
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\ArbiterRender;
|
||||
use App\Models\Asset;
|
||||
use App\Models\RenderTracker;
|
||||
|
||||
class ThumbnailController extends Controller
|
||||
{
|
||||
private function assetValidationRules()
|
||||
{
|
||||
return [
|
||||
'id' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\Asset', 'id')->where(function($query) {
|
||||
return $query->where('moderated', false);
|
||||
})
|
||||
],
|
||||
'type' => 'regex:/(3D|2D)/i'
|
||||
];
|
||||
}
|
||||
|
||||
private function userValidationRules()
|
||||
{
|
||||
return [
|
||||
'id' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\User', 'id'),
|
||||
],
|
||||
'position' => ['sometimes', 'regex:/(Full|Bust)/i'],
|
||||
'type' => 'regex:/(3D|2D)/i'
|
||||
];
|
||||
}
|
||||
|
||||
private function handleRender(Request $request, string $renderType, bool $assetId = null)
|
||||
{
|
||||
$validator = Validator::make($request->all(), $this->{strtolower($renderType) . 'ValidationRules'}());
|
||||
|
||||
if($validator->fails())
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
|
||||
$valid = $validator->valid();
|
||||
$model = ('App\\Models\\' . $renderType)::where('id', $valid['id'])->first();
|
||||
|
||||
$valid['type'] = strtolower($valid['type']);
|
||||
|
||||
if($renderType == 'User') {
|
||||
if($model->hasActivePunishment() && $model->getPunishment()->isDeletion())
|
||||
{
|
||||
$validator->errors()->add('id', 'User is moderated');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
if(!array_key_exists('position', $valid))
|
||||
$valid['position'] = 'Full';
|
||||
|
||||
$valid['position'] = strtolower($valid['position']);
|
||||
|
||||
if($valid['position'] != 'full' && $valid['type'] == '3d')
|
||||
{
|
||||
$validator->errors()->add('type', 'Cannot render non-full avatar as 3D.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
switch($valid['position'])
|
||||
{
|
||||
case 'full':
|
||||
if($model->thumbnail2DHash && $valid['type'] == '2d')
|
||||
return response(['status' => 'success', 'data' => route('content', $model->thumbnail2DHash)]);
|
||||
break;
|
||||
case 'bust':
|
||||
if($model->thumbnailBustHash && $valid['type'] == '2d')
|
||||
return response(['status' => 'success', 'data' => route('content', $model->thumbnailBustHash)]);
|
||||
break;
|
||||
}
|
||||
} elseif($renderType == 'Asset') {
|
||||
if($model->renderId)
|
||||
$model = Asset::where('id', $model->renderId)->first();
|
||||
|
||||
if($model->moderated)
|
||||
return response(['status' => 'success', 'data' => '/thumbs/DeletedThumbnail.png']);
|
||||
|
||||
if(!$model->approved)
|
||||
return response(['status' => 'success', 'data' => '/thumbs/PendingThumbnail.png']);
|
||||
|
||||
if(!$model->assetType->renderable)
|
||||
return response(['status' => 'success', 'data' => '/thumbs/UnavailableThumbnail.png']);
|
||||
|
||||
if(!$model->{$valid['type'] == '3d' ? 'canRender3D' : 'isRenderable'}()) {
|
||||
$validator->errors()->add('id', 'This asset cannot be rendered.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
if($model->thumbnail2DHash && $valid['type'] == '2d')
|
||||
return response(['status' => 'success', 'data' => route('content', $model->thumbnail2DHash)]);
|
||||
}
|
||||
|
||||
if($model->thumbnail3DHash && $valid['type'] == '3d')
|
||||
return response(['status' => 'success', 'data' => route('content', $model->thumbnail3DHash)]);
|
||||
|
||||
$trackerType = sprintf('%s%s', strtolower($renderType), $valid['type']);
|
||||
if($renderType == 'User' && $valid['position'] == 'bust')
|
||||
$trackerType .= 'bust';
|
||||
$tracker = RenderTracker::where('type', $trackerType)
|
||||
->where('target', $model->id)
|
||||
->where('created_at', '>', Carbon::now()->subMinute());
|
||||
|
||||
if(!$tracker->exists()) {
|
||||
$tracker = RenderTracker::create([
|
||||
'type' => $trackerType,
|
||||
'target' => $model->id
|
||||
]);
|
||||
|
||||
ArbiterRender::dispatch(
|
||||
$tracker,
|
||||
$valid['type'] == '3d',
|
||||
($renderType == 'User' ? $valid['position'] == 'full' ? 'Avatar' : 'Bust' : $model->typeString()),
|
||||
$model->id
|
||||
);
|
||||
}
|
||||
|
||||
return response(['status' => 'loading']);
|
||||
}
|
||||
|
||||
public function renderAsset(Request $request)
|
||||
{
|
||||
return $this->handleRender($request, 'Asset');
|
||||
}
|
||||
|
||||
public function renderUser(Request $request)
|
||||
{
|
||||
return $this->handleRender($request, 'User');
|
||||
}
|
||||
|
||||
public function tryAsset(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'id' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\Asset', 'id')->where(function($query) {
|
||||
return $query->where('moderated', false);
|
||||
})
|
||||
]
|
||||
]);
|
||||
|
||||
if($validator->fails())
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
|
||||
$valid = $validator->valid();
|
||||
|
||||
return $this->handleRender($request, 'User', $valid['id']);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Apis;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
use App\Helpers\JSON;
|
||||
use App\Helpers\GridHelper;
|
||||
use App\Helpers\ErrorHelper;
|
||||
|
||||
use App\Models\FFlag;
|
||||
use App\Models\Fbucket;
|
||||
|
||||
class AppSettings extends Controller
|
||||
{
|
||||
/**
|
||||
* A list of flag prefixes
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $prefixes = [
|
||||
'Unscoped' => '',
|
||||
'Fast' => 'F',
|
||||
'Dynamic' => 'DF',
|
||||
'Synchronised' => 'SF'
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of flag types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $types = [
|
||||
'Log' => 'Log',
|
||||
'Int' => 'Int',
|
||||
'String' => 'String',
|
||||
'Boolean' => 'Flag'
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns a JSON array of settings for the specified bucket.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $bucketName
|
||||
* @return Response
|
||||
*/
|
||||
public function getBucket(Request $request, $bucketName)
|
||||
{
|
||||
$primaryBucket = Fbucket::where('name', $bucketName);
|
||||
|
||||
if($primaryBucket->exists()) {
|
||||
$primaryBucket = $primaryBucket->first();
|
||||
|
||||
$bucketIds = [ $primaryBucket->id ];
|
||||
$bucketIds = array_merge($bucketIds, json_decode($primaryBucket->inheritedGroupIds));
|
||||
|
||||
if($primaryBucket->protected == 1 && !GridHelper::hasAllAccess($request)) {
|
||||
return ErrorHelper::error([
|
||||
'code' => 2,
|
||||
'message' => 'You do not have access to this bucket.'
|
||||
], 401);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
$flags = [];
|
||||
|
||||
foreach($bucketIds as $bucket) {
|
||||
$fflags = FFlag::where('bucketId', $bucket)->get();
|
||||
|
||||
foreach($fflags as $flag) {
|
||||
$prefix = $this->prefixes[$flag->type];
|
||||
$dataType = $this->types[$flag->dataType];
|
||||
|
||||
$name = '';
|
||||
if($flag->type != 'Unscoped') {
|
||||
$name = ($prefix . $dataType);
|
||||
}
|
||||
|
||||
$name .= $flag->name;
|
||||
|
||||
$flags[$name] = $flag->value;
|
||||
}
|
||||
}
|
||||
|
||||
ksort($flags);
|
||||
|
||||
return JSON::EncodeResponse($flags);
|
||||
} else {
|
||||
return ErrorHelper::error([
|
||||
'code' => 1,
|
||||
'message' => 'The requested bucket does not exist.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Apis;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Models\WebsiteConfiguration;
|
||||
use App\Helpers\GridHelper;
|
||||
|
||||
class VersionCompatibility extends Controller
|
||||
{
|
||||
function getVersions(Request $request)
|
||||
{
|
||||
if(!GridHelper::hasAllAccess($request)) {
|
||||
return ErrorHelper::error([
|
||||
'code' => 1,
|
||||
'message' => 'You do not have access to this resource.'
|
||||
], 401);
|
||||
}
|
||||
|
||||
return Response()->json([
|
||||
'data' => [
|
||||
explode(';', WebsiteConfiguration::where('name', 'VersionCompatibilityVersions')->first()->value)
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
function getMD5Hashes(Request $request)
|
||||
{
|
||||
if(!GridHelper::hasAllAccess($request)) {
|
||||
return ErrorHelper::error([
|
||||
'code' => 1,
|
||||
'message' => 'You do not have access to this resource.'
|
||||
], 401);
|
||||
}
|
||||
|
||||
return Response()->json([
|
||||
'data' => [
|
||||
explode(';', WebsiteConfiguration::where('name', 'VersionCompatibilityHashes')->first()->value)
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Helpers\AuthHelper;
|
||||
use Auth;
|
||||
use App\Models\User;
|
||||
|
||||
class AuthController extends Controller
|
||||
{
|
||||
/**
|
||||
* Creates an account for the user.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function Register(Request $request) {
|
||||
if(AuthHelper::Guard($request))
|
||||
return Response(null, 400);
|
||||
|
||||
/* */
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
if ($request->input('password') != $request->input('confirmation'))
|
||||
return Response()->json(['message'=>'The passwords you supplied don\'t match!', 'badInputs'=>['password','confirmation']]);
|
||||
|
||||
$valid = Validator::make(
|
||||
$data,
|
||||
[
|
||||
'username' => ['required', 'string', 'regex:/[a-zA-Z0-9._]+/', 'max:20'],
|
||||
'email' => ['required', 'string', 'email', 'max:255'],
|
||||
'password' => ['required', 'string', 'min:8'],
|
||||
]
|
||||
);
|
||||
|
||||
if ($valid->stopOnFirstFailure()->fails()) {
|
||||
$error = $valid->errors()->first();
|
||||
$messages = $valid->messages()->get('*');
|
||||
return Response()->json(['message'=>$error, 'badInputs'=>[array_keys($messages)]]);
|
||||
}
|
||||
|
||||
if(User::where('username', $data['username'])->first())
|
||||
return Response()->json(['message'=>'This user already exists.', 'badInputs'=>['username']]);
|
||||
|
||||
if(User::where('email', $data['email'])->first())
|
||||
return Response()->json(['message'=>'This email is already in use!', 'badInputs'=>['email']]);
|
||||
|
||||
$user = new User();
|
||||
$user->username = $data['username'];
|
||||
$user->email = $data['email'];
|
||||
$user->password = Hash::make($data['password']);
|
||||
$user->about = 'I\'m new to Graphictoria!';
|
||||
$user->save();
|
||||
|
||||
$request->session()->regenerate();
|
||||
|
||||
$newSession = AuthHelper::GrantSession($request, $user->id);
|
||||
$request->session()->put('authentication', $newSession->token);
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the user in.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function Login(Request $request) {
|
||||
if(AuthHelper::Guard($request))
|
||||
return Response(null, 400);
|
||||
|
||||
/* */
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
$valid = Validator::make(
|
||||
$data,
|
||||
[
|
||||
'username' => ['required', 'string'],
|
||||
'password' => ['required', 'string'],
|
||||
]
|
||||
);
|
||||
|
||||
if ($valid->stopOnFirstFailure()->fails()) {
|
||||
$error = $valid->errors()->first();
|
||||
$messages = $valid->messages()->get('*');
|
||||
|
||||
return Response()->json(['message'=>$error, 'badInputs'=>[array_keys($messages)]]);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
$user = User::where('username', $request->input('username'))->first();
|
||||
if (!$user)
|
||||
return Response()->json(['message'=>'That user doesn\'t exist.', 'badInputs'=>['username']]);
|
||||
|
||||
if (!Hash::check($request->input('password'), $user->password))
|
||||
return Response()->json(['message'=>'The password you tried is incorrect.', 'badInputs'=>['password']]);
|
||||
|
||||
$request->session()->regenerate();
|
||||
|
||||
$newSession = AuthHelper::GrantSession($request, $user->id);
|
||||
|
||||
$request->session()->put('authentication', $newSession->token);
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the user out and kills the session.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function Logout(Request $request) {
|
||||
if(!AuthHelper::Guard($request))
|
||||
return Response(null, 400);
|
||||
|
||||
AuthHelper::RemoveSession($request);
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
return redirect('/');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
use App\Models\Banner;
|
||||
|
||||
class BannerController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a JSON array of on-site banners.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getBanners()
|
||||
{
|
||||
$redis = Cache::store('redis');
|
||||
$content = '[{}]'; // fallback
|
||||
|
||||
if($bannerSettings = $redis->get('bannerSetting'))
|
||||
{
|
||||
$content = $bannerSettings;
|
||||
}
|
||||
else
|
||||
{
|
||||
$banners = Banner::select('type', 'message as text', 'dismissable')
|
||||
->get();
|
||||
|
||||
$response = $banners->toJson();
|
||||
|
||||
$redis->put('bannerSetting', $response, now()->addMinutes(5));
|
||||
|
||||
$content = $response;
|
||||
}
|
||||
|
||||
return response($content)
|
||||
->header('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Blog;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class BlogController extends Controller
|
||||
{
|
||||
public function home()
|
||||
{
|
||||
return view('blog.home');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use App\Models\User;
|
||||
use App\Models\User\UserSession;
|
||||
use App\Models\Post;
|
||||
use App\Models\Reply;
|
||||
use App\Models\Category;
|
||||
use App\Models\Friend;
|
||||
use App\Models\Feed;
|
||||
use App\Models\Item;
|
||||
use App\Models\Selling;
|
||||
use App\Models\Inventory;
|
||||
use App\Models\Staff;
|
||||
use App\Models\Prices;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Helpers\AuthHelper;
|
||||
use Illuminate\Http\Request;
|
||||
use Auth;
|
||||
|
||||
class CatalogController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
/*public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Show the application dashboard.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Support\Renderable
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('home');
|
||||
}
|
||||
|
||||
public function buy(Request $request, $id) {
|
||||
|
||||
$user = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$user) return Response()->json(['message'=>'System Error', 'badInputs'=>['title']]);
|
||||
|
||||
$item = Item::whereId($id)->first();
|
||||
|
||||
if (!$item) return Response()->json(['message'=>'No Item.', 'badInputs'=>['title']]);
|
||||
|
||||
if (!isset($_POST['decision'])) return Response()->json(['message'=>'System Error', 'badInputs'=>['title']]);
|
||||
|
||||
$decision = $_POST['decision'];
|
||||
|
||||
if ($item->current_price > $user->bank) return Response()->json(['message'=>"Sorry, you don't have enough currency!", 'badInputs'=>['title']]);
|
||||
|
||||
switch($decision) {
|
||||
case 'nonLimited':
|
||||
|
||||
$newInventory = new Inventory;
|
||||
$newInventory->item_id = $item->id;
|
||||
$newInventory->owner_id = $user->id;
|
||||
$newInventory->owner_type = 'App\Models\User';
|
||||
$newInventory->status = 1;
|
||||
$user->inventory()->save($newInventory);
|
||||
$newInventory->uid = 'nonLimited';
|
||||
$newInventory->save();
|
||||
|
||||
$user->decrement('bank', $item->current_price);
|
||||
$user->save();
|
||||
|
||||
$replies = $item->sellingPrices()->orderBy('price', 'asc')->paginate(10);
|
||||
|
||||
$itemA = $item->toArray();
|
||||
|
||||
$itemA['creator'] = User::where('id', $item->creator_id)->first();
|
||||
|
||||
foreach ($replies as &$reply) {
|
||||
$creator = User::where('id', $reply['seller_id'])->first();
|
||||
if ($creator->id == $user->id) {$reply['isMeta'] = true;}else{$reply['isMeta'] = false;}
|
||||
$reply['created_at'] = explode('T', $reply['created_at'])[0];
|
||||
$reply['seller_name'] = $creator->username;
|
||||
}
|
||||
|
||||
return Response()->json(['message'=>"Success!", 'badInputs'=>[], "item"=>$itemA, "sellingPrices"=>$replies]);
|
||||
|
||||
break;
|
||||
case 'limited':
|
||||
|
||||
if ($item->stock <= 0) return Response()->json(['message'=>"Sorry, there's no more in stock for this item!", 'badInputs'=>['title']]);
|
||||
|
||||
$newInventory = new Inventory;
|
||||
$newInventory->item_id = $item->id;
|
||||
$newInventory->owner_id = $user->id;
|
||||
$newInventory->owner_type = 'App\Models\User';
|
||||
$newInventory->status = 1;
|
||||
$user->inventory()->save($newInventory);
|
||||
$newInventory->uid = $newInventory->id;
|
||||
$newInventory->save();
|
||||
|
||||
$user->decrement('bank', $item->current_price);
|
||||
$user->save();
|
||||
|
||||
$item->decrement('stock');
|
||||
$item->save();
|
||||
|
||||
$replies = $item->sellingPrices()->orderBy('price', 'asc')->paginate(10);
|
||||
|
||||
$itemA = $item->toArray();
|
||||
|
||||
$itemA['creator'] = User::where('id', $item->creator_id)->first();
|
||||
|
||||
foreach ($replies as &$reply) {
|
||||
$creator = User::where('id', $reply['seller_id'])->first();
|
||||
if ($creator->id == $user->id) {$reply['isMeta'] = true;}else{$reply['isMeta'] = false;}
|
||||
$reply['created_at'] = explode('T', $reply['created_at'])[0];
|
||||
$reply['seller_name'] = $creator->username;
|
||||
}
|
||||
|
||||
return Response()->json(['message'=>"Success!", 'badInputs'=>[], "item"=>$itemA, "sellingPrices"=>$replies]);
|
||||
|
||||
break;
|
||||
case 'selling':
|
||||
|
||||
if (!isset($_POST['sellingId'])) return Response()->json(['message'=>'No Selling ID.', 'badInputs'=>['title']]);
|
||||
|
||||
$sellingId = $_POST['sellingId'];
|
||||
|
||||
$sellingItem = Selling::whereId($sellingId)->first();
|
||||
|
||||
if (!$sellingItem) return Response()->json(['message'=>"That selling item doesn't exist!", 'badInputs'=>['title']]);
|
||||
|
||||
if ($sellingItem->seller_id == $user->id) return Response()->json(['message'=>"Thats you!", 'badInputs'=>['title']]);
|
||||
|
||||
$seller = User::where('id', $sellingItem->seller_id)->first();
|
||||
|
||||
$ownedItem = Inventory::where('owner_id', $sellingItem->seller_id)->where('item_id', $item->id)->first();
|
||||
|
||||
if ($sellingItem->price > $user->bank) return Response()->json(['message'=>"Sorry, you don't have enough currency!", 'badInputs'=>['title']]);
|
||||
|
||||
$newInventory = new Inventory;
|
||||
$newInventory->item_id = $item->id;
|
||||
$newInventory->owner_id = $user->id;
|
||||
$newInventory->owner_type = 'App\Models\User';
|
||||
$newInventory->status = 1;
|
||||
$user->inventory()->save($newInventory);
|
||||
$newInventory->uid = $sellingItem->uid;
|
||||
$newInventory->save();
|
||||
|
||||
$user->decrement('bank', $sellingItem->price);
|
||||
$user->save();
|
||||
|
||||
$seller->increment('bank', $sellingItem->price);
|
||||
$seller->save();
|
||||
|
||||
/*$priceNew = new Prices;
|
||||
$priceNew->price = $sellingItem->price;
|
||||
$item->prices()->save($priceNew);*/
|
||||
|
||||
$sellingItem->delete();
|
||||
|
||||
$ownedItem->delete();
|
||||
|
||||
$sellingItemNew = Selling::whereId($sellingId)->first();
|
||||
|
||||
if (count($item->sellingPrices) <= 0) {$item->current_price = null;$item->save();}else{$item->current_price = $sellingItemNew->price;$item->save();}
|
||||
|
||||
$replies = $item->sellingPrices()->orderBy('price', 'asc')->paginate(10);
|
||||
|
||||
$itemA = $item->toArray();
|
||||
|
||||
$itemA['creator'] = User::where('id', $item->creator_id)->first();
|
||||
|
||||
foreach ($replies as &$reply) {
|
||||
$creator = User::where('id', $reply['seller_id'])->first();
|
||||
if ($creator->id == $user->id) {$reply['isMeta'] = true;}else{$reply['isMeta'] = false;}
|
||||
$reply['created_at'] = explode('T', $reply['created_at'])[0];
|
||||
$reply['seller_name'] = $creator->username;
|
||||
}
|
||||
|
||||
return Response()->json(['message'=>"Success!", 'badInputs'=>[], "item"=>$itemA, "sellingPrices"=>$replies]);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function sell(Request $request, $id) {
|
||||
|
||||
$user = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$user) return Response()->json(['message'=>'System Error', 'badInputs'=>['title']]);
|
||||
|
||||
$item = Item::whereId($id)->first();
|
||||
|
||||
if (!$item) return Response()->json(['message'=>'System Error', 'badInputs'=>['title']]);
|
||||
|
||||
if (!$user->ownsItem($id)) return Response()->json(['message'=>"You don't own this item!", 'badInputs'=>['title']]);
|
||||
|
||||
$inventory = Inventory::where('item_id', $id)->where('owner_id', $user->id)->first();
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
$valid = Validator::make($data, [
|
||||
'price' => ['required', 'integer', 'min:1'],
|
||||
]);
|
||||
|
||||
if ($valid->stopOnFirstFailure()->fails()) {
|
||||
$error = $valid->errors()->first();
|
||||
$messages = $valid->messages()->get('*');
|
||||
return Response()->json(['message'=>$error, 'badInputs'=>[array_keys($messages)]]);
|
||||
}
|
||||
|
||||
$selling = new Selling;
|
||||
$selling->seller_id = $user->id;
|
||||
$selling->uid = $inventory->uid;
|
||||
$selling->price = $request->input('price');
|
||||
$item->sellingPrices()->save($selling);
|
||||
|
||||
$sellingItemNew = Selling::where('item_id', $id)->first();
|
||||
|
||||
if ($item->sellingPrices()->count() <= 0) {$item->current_price = null;$item->save();}else{$item->current_price = $sellingItemNew->price;$item->save();}
|
||||
|
||||
$replies = $item->sellingPrices()->orderBy('price', 'asc')->paginate(10);
|
||||
|
||||
$itemA = $item->toArray();
|
||||
|
||||
$itemA['creator'] = User::where('id', $item->creator_id)->first();
|
||||
|
||||
foreach ($replies as &$reply) {
|
||||
$creator = User::where('id', $reply['seller_id'])->first();
|
||||
if ($creator->id == $user->id) {$reply['isMeta'] = true;}else{$reply['isMeta'] = false;}
|
||||
$reply['created_at'] = explode('T', $reply['created_at'])[0];
|
||||
$reply['seller_name'] = $creator->username;
|
||||
}
|
||||
|
||||
return Response()->json(['message'=>"Success!", 'badInputs'=>[], "item"=>$itemA, "sellingPrices"=>$replies]);
|
||||
|
||||
}
|
||||
|
||||
public function removeSale(Request $request, $id) {
|
||||
|
||||
$user = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$user) return Response()->json(['message'=>'System Error', 'badInputs'=>['title']]);
|
||||
|
||||
$sellingId = $id;
|
||||
|
||||
$sellingItem = Selling::whereId($sellingId)->first();
|
||||
|
||||
if (!$sellingItem) return Response()->json(['message'=>"That selling item doesn't exist!", 'badInputs'=>['title']]);
|
||||
|
||||
if ($sellingItem->seller_id != $user->id) return Response()->json(['message'=>"Thats not you!", 'badInputs'=>['title']]);
|
||||
|
||||
$item = Item::whereId($sellingItem->item_id)->first();
|
||||
|
||||
if (!$sellingItem) return Response()->json(['message'=>"That item doesn't exist!", 'badInputs'=>['title']]);
|
||||
|
||||
$sellingItem->delete();
|
||||
|
||||
if (count($item->sellingPrices) <= 0) {$item->current_price = null;$item->save();}else{$item->current_price = $sellingItemNew->price;$item->save();}
|
||||
|
||||
$replies = $item->sellingPrices()->orderBy('price', 'asc')->paginate(10);
|
||||
|
||||
$itemA = $item->toArray();
|
||||
|
||||
$itemA['creator'] = User::where('id', $item->creator_id)->first();
|
||||
|
||||
foreach ($replies as &$reply) {
|
||||
$creator = User::where('id', $reply['seller_id'])->first();
|
||||
if ($creator->id == $user->id) {$reply['isMeta'] = true;}else{$reply['isMeta'] = false;}
|
||||
$reply['created_at'] = explode('T', $reply['created_at'])[0];
|
||||
$reply['seller_name'] = $creator->username;
|
||||
}
|
||||
|
||||
return Response()->json(['message'=>"Success!", 'badInputs'=>[], "item"=>$itemA, "sellingPrices"=>$replies]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Cdn;
|
||||
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Models\CdnHash;
|
||||
use App\Helpers\CdnHelper;
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class CdnController extends Controller
|
||||
{
|
||||
public function getContent(Request $request, $hash)
|
||||
{
|
||||
$disk = CdnHelper::GetDisk();
|
||||
|
||||
if(preg_match('/^[a-f0-9]{64}$/i', $hash) && $disk->exists($hash)) {
|
||||
$content = CdnHash::where('hash', $hash)->first();
|
||||
|
||||
if(!$content || $content->deleted)
|
||||
return response('This item is currently unavailable.')
|
||||
->header('content-type', 'text/plain');
|
||||
|
||||
return response($disk->get($hash))
|
||||
->header('content-type', $content->mime_type);
|
||||
} else {
|
||||
return response('Invalid hash.')
|
||||
->header('content-type', 'text/plain');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,9 +5,202 @@ namespace App\Http\Controllers;
|
|||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use App\Models\User;
|
||||
use App\Models\User\UserSession;
|
||||
use App\Models\Category;
|
||||
use App\Models\Post;
|
||||
use App\Models\Reply;
|
||||
use App\Models\Staff;
|
||||
use App\Models\CatalogCategory;
|
||||
use App\Models\Friend;
|
||||
use App\Models\Feed;
|
||||
use App\Models\Item;
|
||||
use App\Models\Inventory;
|
||||
use App\Models\Selling;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Helpers\AuthHelper;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Carbon;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use DateTime;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
|
||||
public function fetchCategoriesFP(Request $request) {
|
||||
|
||||
$user = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$user) {return Response()->json(["error"=>"No user."]);}
|
||||
|
||||
$staff = Staff::where('user_id', $user->id)->first();
|
||||
|
||||
if ($staff) {$categories = Category::get();}else{$categories = Category::where('staffOnly', '0')->get();}
|
||||
|
||||
return Response()->json(["categories"=>$categories]);
|
||||
}
|
||||
|
||||
public function fetchCategories() {
|
||||
|
||||
$categories = Category::orderBy('staffOnly', 'desc')->get();
|
||||
|
||||
return Response()->json(["categories"=>$categories]);
|
||||
|
||||
}
|
||||
|
||||
public function fetchCategoriesCatalog(Request $request) {
|
||||
|
||||
$categories = CatalogCategory::get();
|
||||
|
||||
return Response()->json(["categories"=>$categories]);
|
||||
|
||||
}
|
||||
|
||||
public function fetchFeed(Request $request) {
|
||||
|
||||
$user = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$user) {return Response()->json(["error"=>"No user."]);}
|
||||
|
||||
$friends = Friend::where('status', 1)->where('recieved_id', $user->id)->orWhere('sent_id', $user->id)->get()->toArray();
|
||||
$actualFriends = [];
|
||||
|
||||
foreach ($friends as $friend) {
|
||||
if ($friend['recieved_id'] == $user->id) {
|
||||
array_push($actualFriends, $friend['sent_id']);
|
||||
}else{
|
||||
array_push($actualFriends, $friend['recieved_id']);
|
||||
}
|
||||
}
|
||||
|
||||
$feed = Feed::whereIn('user_id', $actualFriends)->orWhere('user_id', $user->id)->orderBy('created_at', 'desc')->paginate(15);
|
||||
|
||||
foreach ($feed as &$singleFeed) {
|
||||
$creator = User::where('id', $singleFeed['user_id'])->first();
|
||||
$singleFeed['creatorName'] = $creator->username;
|
||||
}
|
||||
|
||||
return Response()->json(["data"=>$feed]);
|
||||
|
||||
}
|
||||
|
||||
public function fetchCategoryCatalog(Request $request, $id) {
|
||||
|
||||
$category = CatalogCategory::where('id', $id)->first();
|
||||
|
||||
if (!$category) {return Response()->json(false);}
|
||||
|
||||
$items = $category->items()->orderBy('updated_at', 'desc')->paginate(25);
|
||||
|
||||
foreach ($items as &$item) {
|
||||
$item['creator'] = User::where('id', $item['creator_id'])->first();
|
||||
}
|
||||
|
||||
return Response()->json(["data"=>$category, "items"=>$items]);
|
||||
}
|
||||
|
||||
public function fetchCategory(Request $request, $id) {
|
||||
|
||||
$category = Category::where('id', $id)->first();
|
||||
|
||||
if (!$category) {return Response()->json(false);}
|
||||
|
||||
$posts = $category->posts()->orderBy('pinned', 'desc')->orderBy('updated_at', 'desc')->paginate(15);
|
||||
|
||||
foreach ($posts as &$post) {
|
||||
$post['creator'] = User::where('id', $post['creator_id'])->first();
|
||||
}
|
||||
|
||||
return Response()->json(["data"=>$category, "posts"=>$posts]);
|
||||
}
|
||||
|
||||
public function fetchUser(Request $request, $id) {
|
||||
|
||||
$meta = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
$user = User::where('id', $id)->first();
|
||||
|
||||
if (!$user) {return Response()->json('Error');}
|
||||
|
||||
$array = $user->toArray();
|
||||
|
||||
if ($meta && $meta->id == $array['id']) $array['isMeta'] = true; else $array['isMeta'] = false;
|
||||
|
||||
if ($meta && $meta->getFriends('pending', 'checkSent', $array['id'])) $array['isFriend'] = 'needToAccept'; elseif ($meta && array_intersect($meta->getFriends('pending', 'id', null), [$array['id']])) $array['isFriend'] = 'pending'; elseif ($meta && array_intersect($meta->getFriends('id', null, null), [$array['id']])) $array['isFriend'] = true; else $array['isFriend'] = false;
|
||||
|
||||
return Response()->json(["data"=>$array]);
|
||||
}
|
||||
|
||||
public function fetchPost(Request $request, $id) {
|
||||
|
||||
$post = Post::where('id', $id)->first();
|
||||
|
||||
if (!$post) {return Response()->json(false);}
|
||||
|
||||
$postA = $post->toArray();
|
||||
|
||||
$realDate = explode('T', $postA['created_at'])[0];
|
||||
|
||||
$postA['created_at'] = $realDate;
|
||||
|
||||
$postA['creator'] = User::where('id', $postA['creator_id'])->first();
|
||||
|
||||
$replies = $post->replies()->orderBy('pinned', 'desc')->orderBy('created_at', 'asc')->paginate(10);
|
||||
|
||||
foreach ($replies as &$reply) {
|
||||
$creator = User::where('id', $reply['creator_id'])->first();
|
||||
$reply['created_at'] = explode('T', $reply['created_at'])[0];
|
||||
$reply['creator_name'] = $creator->username;
|
||||
}
|
||||
|
||||
return Response()->json(["post"=>$postA,"replies"=>$replies]);
|
||||
}
|
||||
|
||||
public function fetchItem(Request $request, $id) {
|
||||
|
||||
$user = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
$item = Item::where('id', $id)->first();
|
||||
|
||||
if (!$item) return Response()->json(false);
|
||||
|
||||
$itemA = $item->toArray();
|
||||
|
||||
$realDate = explode('T', $itemA['created_at'])[0];
|
||||
|
||||
$itemA['created_at'] = $realDate;
|
||||
|
||||
$itemA['creator'] = User::where('id', $item->creator_id)->first();
|
||||
|
||||
if ($user) {
|
||||
$sellingItem = Selling::where('seller_id', $user->id)->first();
|
||||
if ($sellingItem) {
|
||||
$itemA['isSelling'] = true;
|
||||
} else {
|
||||
$itemA['isSelling'] = false;
|
||||
}
|
||||
} else {
|
||||
$itemA['isSelling'] = false;
|
||||
}
|
||||
|
||||
if ($user && $user->ownsItem($id)) {$itemA['ownsItem'] = true;}else{$itemA['ownsItem'] = false;}
|
||||
|
||||
$replies = $item->sellingPrices()->orderBy('price', 'asc')->paginate(10);
|
||||
|
||||
foreach ($replies as &$reply) {
|
||||
$creator = User::where('id', $reply['seller_id'])->first();
|
||||
if ($creator->id == $user->id) {$reply['isMeta'] = true;}else{$reply['isMeta'] = false;}
|
||||
$reply['created_at'] = explode('T', $reply['created_at'])[0];
|
||||
$reply['seller_name'] = $creator->username;
|
||||
}
|
||||
|
||||
return Response()->json(["item"=>$itemA,"sellingPrices"=>$replies]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Models\Games;
|
||||
use App\Models\WebStatus;
|
||||
|
||||
class GamesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns if the games arbiter is operational or not.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function isAvailable()
|
||||
{
|
||||
$status = WebStatus::where('name', 'GamesArbiter')
|
||||
->first();
|
||||
|
||||
if (!$status) return response()->json(['error' => false])
|
||||
->header('Content-Type', 'application/json');
|
||||
|
||||
return response()->json(['available' => $status->operational])
|
||||
->header('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
public function validatePlaceJoin()
|
||||
{
|
||||
// todo: move to backend and make this actually return if the player is validated
|
||||
// this is only here for testing
|
||||
|
||||
return response('true', null)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Grid\SoapService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class GridTest extends Controller
|
||||
{
|
||||
/**
|
||||
* @return Response
|
||||
*/
|
||||
public function generateThumbnail()
|
||||
{
|
||||
$testScript = <<<TestScript
|
||||
settings()["Task Scheduler"].ThreadPoolConfig = Enum.ThreadPoolConfig.PerCore4;
|
||||
game:GetService("ContentProvider"):SetThreadPool(16)
|
||||
game:GetService("Stats"):SetReportUrl("http://api.gtoria.net/teststat")
|
||||
|
||||
game:GetService("ContentProvider"):SetBaseUrl("http://www.roblox.com/")
|
||||
game:LoadWorld(23173663)
|
||||
|
||||
return game:GetService("ThumbnailGenerator"):Click("PNG", 1920, 1080, false, false)
|
||||
TestScript;
|
||||
|
||||
$test = new SoapService('http://127.0.0.1:64989');
|
||||
$result = $test->OpenJob(SoapService::MakeJobJSON('test', 10, 0, 0, 'test render', $testScript));
|
||||
|
||||
return response(base64_decode($result->OpenJobExResult->LuaValue[0]->value))
|
||||
->header('Content-Type', 'image/png');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use App\Models\User;
|
||||
use App\Models\User\UserSession;
|
||||
use App\Models\Post;
|
||||
use App\Models\Reply;
|
||||
use App\Models\Category;
|
||||
use App\Models\Friend;
|
||||
use App\Models\Feed;
|
||||
use App\Models\Staff;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Helpers\AuthHelper;
|
||||
use Illuminate\Http\Request;
|
||||
use Auth;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
/*public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Show the application dashboard.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Support\Renderable
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('home');
|
||||
}
|
||||
|
||||
public function createPost(Request $request) {
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
$valid = Validator::make($data, [
|
||||
'title' => ['required', 'string', 'min:3', 'max:38'],
|
||||
'body' => ['required', 'string', 'min:3', 'max:380'],
|
||||
'category' => ['required']
|
||||
]);
|
||||
|
||||
if ($valid->stopOnFirstFailure()->fails()) {
|
||||
$error = $valid->errors()->first();
|
||||
$messages = $valid->messages()->get('*');
|
||||
return Response()->json(['message'=>$error, 'badInputs'=>[array_keys($messages)]]);
|
||||
}
|
||||
|
||||
$meta = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$meta) {return Response()->json(['message'=>'System error', 'badInputs'=>['title']]);}
|
||||
|
||||
if (!isset($_POST['creator_id'])) {return Response()->json(['message'=>'System error', 'badInputs'=>['title']]);}
|
||||
|
||||
$user = User::where('id', $_POST['creator_id'])->first();
|
||||
|
||||
if (!$user) {return Response()->json(['message'=>'User not found!', 'badInputs'=>['title']]);}
|
||||
|
||||
if (!isset($_POST['category'])) {return Response()->json(['message'=>'Category not found!', 'badInputs'=>['category']]);}
|
||||
|
||||
$categoryId = $_POST['category'];
|
||||
|
||||
$category = Category::where('id', $categoryId)->first();
|
||||
|
||||
$staff = Staff::where('user_id', $user->id)->first();
|
||||
|
||||
if ($category->staffOnly == '1' && !$staff) {return Response()->json(['message'=>'You cant use that category.', 'badInputs'=>['category']]);}
|
||||
|
||||
$post = new Post;
|
||||
$post->title = $_POST['title'];
|
||||
$post->body = $_POST['body'];
|
||||
$post->creator_id = $_POST['creator_id'];
|
||||
$category->posts()->save($post);
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[], 'post_id'=>$post->id]);
|
||||
|
||||
}
|
||||
|
||||
public function createFeed(Request $request) {
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
$valid = Validator::make($data, [
|
||||
'body' => ['required', 'string', 'min:3', 'max:245'],
|
||||
]);
|
||||
|
||||
if ($valid->stopOnFirstFailure()->fails()) {
|
||||
$error = $valid->errors()->first();
|
||||
$messages = $valid->messages()->get('*');
|
||||
return Response()->json(['message'=>$error, 'badInputs'=>[array_keys($messages)]]);
|
||||
}
|
||||
|
||||
$user = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$user) {return Response()->json(['message'=>'System error', 'badInputs'=>['title']]);}
|
||||
|
||||
$feed = new Feed;
|
||||
$feed->user_id = $user->id;
|
||||
$feed->body = $request->input('body');
|
||||
$feed->save();
|
||||
|
||||
$friends = Friend::where('status', 1)->where('recieved_id', $user->id)->orWhere('sent_id', $user->id)->get()->toArray();
|
||||
$actualFriends = [];
|
||||
|
||||
foreach ($friends as $friend) {
|
||||
if ($friend['recieved_id'] == $user->id) {
|
||||
array_push($actualFriends, $friend['sent_id']);
|
||||
}else{
|
||||
array_push($actualFriends, $friend['recieved_id']);
|
||||
}
|
||||
}
|
||||
|
||||
$newFeed = Feed::whereIn('user_id', $actualFriends)->orWhere('user_id', $user->id)->orderBy('created_at', 'desc')->paginate(15);
|
||||
|
||||
foreach ($newFeed as &$singleFeed) {
|
||||
$creator = User::where('id', $singleFeed['user_id'])->first();
|
||||
$singleFeed['creatorName'] = $creator->username;
|
||||
}
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[], "data"=>$newFeed]);
|
||||
|
||||
}
|
||||
|
||||
public function addFriend(Request $request, $id) {
|
||||
|
||||
$user = User::where('id', $id)->first();
|
||||
|
||||
if (!$user) {return Response()->json(['message'=>'No user.', 'badInputs'=>['title']]);}
|
||||
|
||||
$meta = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$meta) {return Response()->json(['message'=>'System error.', 'badInputs'=>['title']]);}
|
||||
|
||||
if (!isset($_POST['decision'])) {return Response()->json(['message'=>'System error.', 'badInputs'=>['title']]);}
|
||||
|
||||
switch($_POST['decision']) {
|
||||
case 'remove':
|
||||
if ($meta && !array_intersect($meta->getFriends('id', null, null), [$user->id]))
|
||||
return Response()->json(['message'=>'Not Friends.', 'badInputs'=>['title']]);
|
||||
elseif ($meta && array_intersect($meta->getFriends('pending', 'id', null), [$user->id]))
|
||||
return Response()->json(['message'=>'Already Pending.', 'badInputs'=>['title']]);
|
||||
|
||||
$friend = $meta->getFriends('remove', null, $user->id);
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[], "data"=>false]);
|
||||
break;
|
||||
case 'accept':
|
||||
if ($meta && array_intersect($meta->getFriends('id', null, null), [$user->id]))
|
||||
return Response()->json(['message'=>'Already Friends.', 'badInputs'=>['title']]);
|
||||
|
||||
$friend = $meta->getFriends('accept', null, $user->id);
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[], "data"=>true]);
|
||||
break;
|
||||
case 'add':
|
||||
if ($meta && array_intersect($meta->getFriends('id', null, null), [$user->id]))
|
||||
return Response()->json(['message'=>'Already Friends.', 'badInputs'=>['title']]);
|
||||
elseif ($meta && array_intersect($meta->getFriends('pending', 'id', null), [$user->id]))
|
||||
return Response()->json(['message'=>'Already Pending.', 'badInputs'=>['title']]);
|
||||
|
||||
$friend = new Friend;
|
||||
$friend->sent_id = $meta->id;
|
||||
$friend->recieved_id = $user->id;
|
||||
$friend->status = 0;
|
||||
$friend->save();
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[], "data"=>'pending']);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function createReply(Request $request, $id) {
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
$valid = Validator::make($data, [
|
||||
'body' => ['required', 'string', 'min:3', 'max:380'],
|
||||
]);
|
||||
|
||||
if ($valid->stopOnFirstFailure()->fails()) {
|
||||
$error = $valid->errors()->first();
|
||||
$messages = $valid->messages()->get('*');
|
||||
return Response()->json(['message'=>$error, 'badInputs'=>[array_keys($messages)]]);
|
||||
}
|
||||
|
||||
$meta = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$meta) {return Response()->json(['message'=>'System error', 'badInputs'=>['title']]);}
|
||||
|
||||
if (!isset($_POST['creator_id'])) {return Response()->json(['message'=>'System error', 'badInputs'=>['title']]);}
|
||||
|
||||
$user = User::where('id', $_POST['creator_id'])->first();
|
||||
|
||||
if (!$user) {return Response()->json(['message'=>'User not found!', 'badInputs'=>['title']]);}
|
||||
|
||||
$post = Post::where('id', $id)->first();
|
||||
|
||||
if (!$post) {return Response()->json(['message'=>'Post not found!', 'badInputs'=>['body']]);}
|
||||
|
||||
if ($post->locked && $user->id != $meta->id) {return Response()->json(['message'=>'This post is locked!', 'badInputs'=>['body']]);}
|
||||
|
||||
$reply = new Reply;
|
||||
$reply->body = $_POST['body'];
|
||||
$reply->creator_id = $user->id;
|
||||
$post->replies()->save($reply);
|
||||
|
||||
$post->touch();
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[], 'post_id'=>$post->id]);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
|
||||
use App\Models\WebsiteConfiguration;
|
||||
|
||||
class MaintenanceController extends Controller
|
||||
{
|
||||
/**
|
||||
* Handles the maintenance bypass request.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function bypass(Request $request)
|
||||
{
|
||||
$password = $request->input('password');
|
||||
$buttons = $request->input('buttons');
|
||||
|
||||
if($password && $buttons)
|
||||
{
|
||||
$mtconf = json_decode(WebsiteConfiguration::whereName('MaintenancePassword')->first()->value);
|
||||
|
||||
if($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 = parse_url($request->headers->get('origin'), PHP_URL_HOST);
|
||||
$passCheck = false;
|
||||
|
||||
foreach($trustedHosts as &$host)
|
||||
{
|
||||
if(str_ends_with($origin, $host))
|
||||
$passCheck = true;
|
||||
}
|
||||
|
||||
$expiresAt = Carbon::now()->addHours(24);
|
||||
$bypassCookie = new Cookie('gt_constraint', base64_encode(json_encode([
|
||||
'expires_at' => $expiresAt->getTimestamp(),
|
||||
'mac' => hash_hmac('SHA256', $expiresAt->getTimestamp(), $data['secret']),
|
||||
])), $expiresAt);
|
||||
|
||||
if($passCheck)
|
||||
$bypassCookie = $bypassCookie->withDomain('.' . $origin);
|
||||
|
||||
return response('')
|
||||
->withCookie($bypassCookie);
|
||||
}
|
||||
}
|
||||
|
||||
return response('')
|
||||
->setStatusCode(403);
|
||||
}
|
||||
else
|
||||
{
|
||||
return response('{"errors":[{"code":400,"message":"BadRequest"}]}')
|
||||
->setStatusCode(400)
|
||||
->header('Cache-Control', 'private')
|
||||
->header('Content-Type', 'application/json; charset=utf-8');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use App\Models\User;
|
||||
use App\Models\User\UserSession;
|
||||
use App\Models\Post;
|
||||
use App\Models\Reply;
|
||||
use App\Models\Category;
|
||||
use App\Models\Friend;
|
||||
use App\Models\Feed;
|
||||
use App\Models\Staff;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Helpers\AuthHelper;
|
||||
use Illuminate\Http\Request;
|
||||
use Auth;
|
||||
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
/*public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Show the application dashboard.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Support\Renderable
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('home');
|
||||
}
|
||||
|
||||
public function settingsAbout(Request $request) {
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
$valid = Validator::make($data, [
|
||||
'body' => ['required', 'string', 'min:2', 'max:180'],
|
||||
]);
|
||||
|
||||
if ($valid->stopOnFirstFailure()->fails()) {
|
||||
$error = $valid->errors()->first();
|
||||
$messages = $valid->messages()->get('*');
|
||||
return Response()->json(['message'=>$error, 'badInputs'=>[array_keys($messages)]]);
|
||||
}
|
||||
|
||||
$user = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
$user->about = $_POST['body'];
|
||||
$user->save();
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[]]);
|
||||
|
||||
}
|
||||
|
||||
public function settingsPassword(Request $request) {
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
$valid = Validator::make($data, [
|
||||
'currentPassword' => ['required', 'string'],
|
||||
'newPassword' => ['required', 'string', 'min:8'],
|
||||
'checkNewPassword' => ['required', 'string'],
|
||||
]);
|
||||
|
||||
if ($valid->stopOnFirstFailure()->fails()) {
|
||||
$error = $valid->errors()->first();
|
||||
$messages = $valid->messages()->get('*');
|
||||
return Response()->json(['message'=>$error, 'badInputs'=>[array_keys($messages)]]);
|
||||
}
|
||||
|
||||
$user = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$user) return Response()->json(['message'=>'User not found!', 'badInputs'=>['title']]);
|
||||
|
||||
if (!Hash::check($request->input('currentPassword'), $user->password))
|
||||
return Response()->json(['message'=>'Thats not the right password!', 'badInputs'=>['currentPassword']]);
|
||||
|
||||
if ($request->input('newPassword') != $request->input('checkNewPassword'))
|
||||
return Response()->json(['message'=>'Those dont match!', 'badInputs'=>['checkNewPassword', 'newPassword']]);
|
||||
|
||||
$user->password = Hash::make($request->input('newPassword'));
|
||||
$user->save();
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[]]);
|
||||
|
||||
}
|
||||
|
||||
public function settingsEmail(Request $request) {
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
$valid = Validator::make($data, [
|
||||
'currentPassword' => ['required', 'string'],
|
||||
'newEmail' => ['required', 'string', 'email', 'max:255'],
|
||||
]);
|
||||
|
||||
if ($valid->stopOnFirstFailure()->fails()) {
|
||||
$error = $valid->errors()->first();
|
||||
$messages = $valid->messages()->get('*');
|
||||
return Response()->json(['message'=>$error, 'badInputs'=>[array_keys($messages)]]);
|
||||
}
|
||||
|
||||
$user = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if (!$user) return Response()->json(['message'=>'User not found!', 'badInputs'=>['title']]);
|
||||
|
||||
if (!Hash::check($request->input('currentPassword'), $user->password))
|
||||
return Response()->json(['message'=>'Thats not the right password!', 'badInputs'=>['currentPassword']]);
|
||||
|
||||
$user->email = $request->input('newEmail');
|
||||
$user->email_verified_at = null;
|
||||
$user->save();
|
||||
|
||||
return Response()->json(['message'=>'Success!', 'badInputs'=>[]]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Setup;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\DynamicWebConfiguration;
|
||||
|
||||
class SetupController extends Controller
|
||||
{
|
||||
public function getFile(Request $request, $file)
|
||||
{
|
||||
$file = basename($file);
|
||||
$filePath = Storage::path('setup/' . $file);
|
||||
|
||||
if(!file_exists($filePath) || strtolower($file) == '.gitignore' || str_ends_with(strtolower($file), 'pdb.zip'))
|
||||
return response('404 not found.', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
|
||||
return response()->file($filePath);
|
||||
}
|
||||
|
||||
public function getClientVersion()
|
||||
{
|
||||
return response(DynamicWebConfiguration::where('name', 'ClientUploadVersion')->first()->value)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
public function getStudioVersion()
|
||||
{
|
||||
return response(DynamicWebConfiguration::where('name', 'StudioUploadVersion')->first()->value)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Helpers\AuthHelper;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
/**
|
||||
* Gets the current user's settings.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function GetSettings(Request $request) {
|
||||
$currentUser = AuthHelper::GetCurrentUser($request);
|
||||
|
||||
if($currentUser) {
|
||||
return Response()->json([
|
||||
'data' => $currentUser
|
||||
]);
|
||||
} else {
|
||||
return Response()->json([
|
||||
'error' => 'Unauthorized',
|
||||
'userFacingMessage' => 'You are not authorized to perform this request.'
|
||||
]);
|
||||
}
|
||||
|
||||
// Not sure how we'd get here, but just in case
|
||||
return Response(null, 400);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,325 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\AdminUpload;
|
||||
use App\Models\DynamicWebConfiguration;
|
||||
use App\Models\PunishmentType;
|
||||
use App\Models\Username;
|
||||
use App\Models\User;
|
||||
use App\Models\UserIp;
|
||||
|
||||
class AdminController extends Controller
|
||||
{
|
||||
function getJs(Request $request, string $jsFile)
|
||||
{
|
||||
$filePath = public_path('js/adm/' . basename($jsFile));
|
||||
|
||||
if(!file_exists($filePath))
|
||||
abort(404);
|
||||
|
||||
return response()->file($filePath);
|
||||
}
|
||||
|
||||
// Moderator+
|
||||
|
||||
// GET admin.dashboard
|
||||
function dashboard()
|
||||
{
|
||||
return view('web.admin.dashboard');
|
||||
}
|
||||
|
||||
// GET admin.useradmin
|
||||
function userAdmin(Request $request)
|
||||
{
|
||||
$user = User::where('id', $request->get('ID'));
|
||||
if(!$user->exists())
|
||||
abort(400);
|
||||
|
||||
return view('web.admin.useradmin')->with('user', $user->first());
|
||||
}
|
||||
|
||||
// GET admin.manualmoderateuser
|
||||
function manualModerateUser(Request $request)
|
||||
{
|
||||
$user = User::where('id', $request->get('ID'));
|
||||
if(!$user->exists())
|
||||
abort(400);
|
||||
|
||||
return view('web.admin.manualmoderateuser')->with('user', $user->first());
|
||||
}
|
||||
|
||||
// POST admin.manualmoderateusersubmit
|
||||
function manualModerateUserSubmit(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'ID' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\User', 'id')
|
||||
],
|
||||
'moderate-action' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\PunishmentType', 'id')
|
||||
],
|
||||
'internal-note' => 'required'
|
||||
], [
|
||||
'moderate-action.required' => 'Please provide an account state.',
|
||||
'internal-note.required' => 'An internal note must be provided on why this user\'s state was changed.'
|
||||
]);
|
||||
|
||||
if($validator->fails())
|
||||
return $this->manualModerateUserError($validator);
|
||||
|
||||
$user = User::where('id', $request->get('ID'))->first();
|
||||
|
||||
if(Auth::user()->id == $user->id)
|
||||
{
|
||||
$validator->errors()->add('ID', 'Cannot apply account state to current user.');
|
||||
return $this->manualModerateUserError($validator);
|
||||
}
|
||||
|
||||
if(
|
||||
($user->hasRoleset('ProtectedUser') && !Auth::user()->hasRoleset('Owner'))
|
||||
|
||||
// XlXi: Prevent lower-ranks from banning higher ranks.
|
||||
|| (
|
||||
($user->hasRoleset('Owner') && !Auth::user()->hasRoleset('Owner'))
|
||||
&& ($user->hasRoleset('Administrator') && !Auth::user()->hasRoleset('Administrator'))
|
||||
)
|
||||
)
|
||||
{
|
||||
$validator->errors()->add('ID', 'User is protected. Contact an owner.');
|
||||
return $this->manualModerateUserError($validator);
|
||||
}
|
||||
|
||||
// XlXi: Moderation action type 1 is None.
|
||||
if($request->get('moderate-action') == 1 && !$user->hasActivePunishment())
|
||||
return $this->manualModerateUserSuccess(sprintf('%s already has an account state of None. No changes applied.', $user->username));
|
||||
|
||||
if($request->get('moderate-action') != 1 && $user->hasActivePunishment())
|
||||
{
|
||||
$validator->errors()->add('ID', 'User already has an active punishment.');
|
||||
return $this->manualModerateUserError($validator);
|
||||
}
|
||||
|
||||
if(Auth::user()->hasRoleset('Administrator'))
|
||||
{
|
||||
if($request->has('scrub-username'))
|
||||
{
|
||||
$newUsername = sprintf('[ Content Deleted %d ]', $user->id);
|
||||
|
||||
Username::where('user_id', $user->id)
|
||||
->update([
|
||||
'scrubbed' => true,
|
||||
'scrubbed_by' => Auth::user()->id
|
||||
]);
|
||||
|
||||
Username::create([
|
||||
'username' => $newUsername,
|
||||
'user_id' => $user->id
|
||||
]);
|
||||
|
||||
$user->username = $newUsername;
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
||||
PunishmentType::where('id', $request->get('moderate-action'))
|
||||
->first()
|
||||
->applyToUser([
|
||||
'user_id' => $user->id,
|
||||
'user_note' => $request->get('user-note') ?: '',
|
||||
'internal_note' => $request->get('internal-note') ?: '',
|
||||
'moderator_id' => Auth::user()->id
|
||||
]);
|
||||
|
||||
return $this->manualModerateUserSuccess(sprintf('Successfully applied account state to %s.', $user->username));
|
||||
}
|
||||
|
||||
function manualModerateUserError($validator)
|
||||
{
|
||||
$user = User::where('id', request()->get('ID'))->first();
|
||||
|
||||
return view('web.admin.manualmoderateuser')
|
||||
->with('user', $user)
|
||||
->withErrors($validator);
|
||||
}
|
||||
|
||||
function manualModerateUserSuccess($message)
|
||||
{
|
||||
$user = User::where('id', request()->get('ID'))->first();
|
||||
|
||||
return view('web.admin.manualmoderateuser')
|
||||
->with('user', $user)
|
||||
->with('success', $message);
|
||||
}
|
||||
|
||||
// GET admin.usersearch
|
||||
function userSearch(Request $request)
|
||||
{
|
||||
$types = [
|
||||
'userid' => 'UserId',
|
||||
'username' => 'UserName',
|
||||
'emailaddress' => 'EmailAddress',
|
||||
'ipaddress' => 'IpAddress'
|
||||
];
|
||||
|
||||
foreach($types as $type => &$func)
|
||||
{
|
||||
if($type == $request->has($type))
|
||||
return $this->{'userSearchQuery' . $func}($request);
|
||||
}
|
||||
|
||||
return view('web.admin.usersearch');
|
||||
}
|
||||
|
||||
// POST admin.usersearchquery
|
||||
function userSearchQueryUserId(Request $request)
|
||||
{
|
||||
$users = User::where('id', $request->get('userid'))
|
||||
->paginate(25)
|
||||
->appends($request->all());
|
||||
|
||||
return view('web.admin.usersearch')->with('users', $users);
|
||||
}
|
||||
|
||||
function userSearchQueryUserName(Request $request)
|
||||
{
|
||||
$users = User::where('username', 'like', '%' . $request->get('username') . '%')
|
||||
->paginate(25)
|
||||
->appends($request->all());
|
||||
|
||||
return view('web.admin.usersearch')->with('users', $users);
|
||||
}
|
||||
|
||||
function userSearchQueryEmailAddress(Request $request)
|
||||
{
|
||||
if(!Auth::user()->hasRoleset('Owner'))
|
||||
abort(403);
|
||||
|
||||
$users = User::where('email', $request->get('emailaddress'))
|
||||
->paginate(25)
|
||||
->appends($request->all());
|
||||
|
||||
return view('web.admin.usersearch')->with('users', $users);
|
||||
}
|
||||
|
||||
function userSearchQueryIpAddress(Request $request)
|
||||
{
|
||||
if(!Auth::user()->hasRoleset('Owner'))
|
||||
abort(403);
|
||||
|
||||
$users = UserIp::where('ipAddress', $request->get('ipaddress'))
|
||||
->join('users', 'users.id', '=', 'user_ips.userId')
|
||||
->orderBy('users.id', 'desc')
|
||||
->paginate(25)
|
||||
->appends($request->all());
|
||||
|
||||
return view('web.admin.usersearch')->with('users', $users)->with('isIpSearch', true);
|
||||
}
|
||||
|
||||
// GET admin.userlookup
|
||||
function userLookup()
|
||||
{
|
||||
return view('web.admin.userlookup');
|
||||
}
|
||||
|
||||
// POST admin.userlookupquery
|
||||
function userLookupQuery(Request $request)
|
||||
{
|
||||
$users = [];
|
||||
|
||||
foreach(preg_split('/\r\n|\r|\n/', $request->get('lookup')) as $username)
|
||||
{
|
||||
$user = User::where('username', $username);
|
||||
|
||||
if($user->exists())
|
||||
{
|
||||
$user = $user->first();
|
||||
array_push(
|
||||
$users,
|
||||
[
|
||||
'found' => true,
|
||||
'user' => $user
|
||||
]
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
array_push(
|
||||
$users,
|
||||
[
|
||||
'found' => false,
|
||||
'username' => $username
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return view('web.admin.userlookup')->with('users', $users)->with('input', $request->get('lookup'));
|
||||
}
|
||||
|
||||
// Admin+
|
||||
|
||||
// GET admin.autoupload
|
||||
function autoUpload()
|
||||
{
|
||||
return view('web.admin.catalog.autoupload');
|
||||
}
|
||||
|
||||
// GET admin.assetupload
|
||||
function assetUpload()
|
||||
{
|
||||
return view('web.admin.catalog.assetupload');
|
||||
}
|
||||
|
||||
// GET admin.adminuploads
|
||||
function getAdminUploads(Request $request)
|
||||
{
|
||||
$uploads = AdminUpload::query()
|
||||
->orderByDesc('id')
|
||||
->paginate(25);
|
||||
|
||||
return view('web.admin.catalog.adminuploads')->with('uploads', $uploads);
|
||||
}
|
||||
|
||||
function metricsVisualization()
|
||||
{
|
||||
return view('web.admin.metricsvisualization');
|
||||
}
|
||||
|
||||
function arbiterDiag(Request $request, string $arbiterType = null)
|
||||
{
|
||||
return view('web.admin.arbiter.diag')->with([
|
||||
'title' => sprintf('%s Arbiter Diag', $arbiterType),
|
||||
'arbiter' => $arbiterType
|
||||
]);
|
||||
}
|
||||
|
||||
// Owner+
|
||||
function arbiterManagement(Request $request, string $arbiterType = null, string $jobId = null)
|
||||
{
|
||||
return view('web.admin.arbiter.management')->with([
|
||||
'title' => sprintf('%s Arbiter Management', $arbiterType),
|
||||
'arbiter' => $arbiterType
|
||||
]);
|
||||
}
|
||||
|
||||
function configuration(Request $request)
|
||||
{
|
||||
return view('web.admin.configuration')->with([
|
||||
'values' => DynamicWebConfiguration::get()
|
||||
]);
|
||||
}
|
||||
|
||||
function deployer()
|
||||
{
|
||||
return view('web.admin.deployer');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Auth;
|
||||
|
||||
use App\Http\Requests\Auth\LoginRequest;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use App\Models\Session;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class AuthenticatedSessionController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the login view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('web.auth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming authentication request.
|
||||
*
|
||||
* @param \App\Http\Requests\Auth\LoginRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(LoginRequest $request)
|
||||
{
|
||||
$request->authenticate();
|
||||
|
||||
$request->session()->regenerate();
|
||||
|
||||
return redirect()->intended(RouteServiceProvider::HOME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an authenticated session.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(Request $request)
|
||||
{
|
||||
Auth::guard('web')->logout();
|
||||
|
||||
$request->session()->invalidate();
|
||||
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return redirect('/');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Auth;
|
||||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class ConfirmablePasswordController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show the confirm password view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
return view('web.auth.confirm-password');
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the user's password.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
if (! Auth::guard('web')->validate([
|
||||
'email' => $request->user()->email,
|
||||
'password' => $request->password,
|
||||
])) {
|
||||
throw ValidationException::withMessages([
|
||||
'password' => __('auth.password'),
|
||||
]);
|
||||
}
|
||||
|
||||
$request->session()->put('auth.password_confirmed_at', time());
|
||||
|
||||
return redirect()->intended(RouteServiceProvider::HOME);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Auth;
|
||||
|
||||
use App\Models\Session;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class DoubleSessionBlockController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return response()
|
||||
->view('web.auth.ddos_blocked', [], 403);
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
request()->validate([
|
||||
'g-recaptcha-response' => [new \App\Rules\GoogleRecaptcha]
|
||||
]);
|
||||
|
||||
request()->session()->put('bypass-block-screen', true);
|
||||
|
||||
$returnUrl = request()->input('ReturnUrl');
|
||||
|
||||
if(!$returnUrl)
|
||||
$returnUrl = '/';
|
||||
|
||||
return redirect(urldecode($returnUrl), 302);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Auth;
|
||||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class EmailVerificationNotificationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Send a new email verification notification.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
if ($request->user()->hasVerifiedEmail()) {
|
||||
return redirect()->intended(RouteServiceProvider::HOME);
|
||||
}
|
||||
|
||||
$request->user()->sendEmailVerificationNotification();
|
||||
|
||||
return back()->with('status', 'verification-link-sent');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Auth;
|
||||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class EmailVerificationPromptController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the email verification prompt.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke(Request $request)
|
||||
{
|
||||
return $request->user()->hasVerifiedEmail()
|
||||
? redirect()->intended(RouteServiceProvider::HOME)
|
||||
: view('web.auth.verify-email');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Auth;
|
||||
|
||||
use Illuminate\Auth\Events\PasswordReset;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rules;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class NewPasswordController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the password reset view.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
return view('web.auth.reset-password', ['request' => $request]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming new password request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'token' => ['required'],
|
||||
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
||||
]);
|
||||
|
||||
// Here we will attempt to reset the user's password. If it is successful we
|
||||
// will update the password on an actual user model and persist it to the
|
||||
// database. Otherwise we will parse the error and return the response.
|
||||
$status = Password::reset(
|
||||
$request->only('password', 'password_confirmation', 'token'),
|
||||
function ($user) use ($request) {
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($request->password),
|
||||
'remember_token' => Str::random(60),
|
||||
])->save();
|
||||
|
||||
event(new PasswordReset($user));
|
||||
}
|
||||
);
|
||||
|
||||
// If the password was successfully reset, we will redirect the user back to
|
||||
// the application's home authenticated view. If there is an error we can
|
||||
// redirect them back to where they came from with their error message.
|
||||
return $status == Password::PASSWORD_RESET
|
||||
? redirect()->route('auth.login.index')->with('status', __($status))
|
||||
: back()->withErrors(['status' => __($status)]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Auth;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class PasswordResetLinkController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the password reset link request view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('web.auth.forgot-password');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming password reset link request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'email' => ['required', 'email'],
|
||||
]);
|
||||
|
||||
// We will send the password reset link to this user. Once we have attempted
|
||||
// to send the link, we will examine the response then see the message we
|
||||
// need to show to the user. Finally, we'll send out a proper response.
|
||||
$status = Password::sendResetLink(
|
||||
$request->only('email')
|
||||
);
|
||||
|
||||
return $status == Password::RESET_LINK_SENT
|
||||
? back()->with('status', __($status))
|
||||
: back()->withInput($request->only('email'))
|
||||
->withErrors(['email' => __($status)]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Auth;
|
||||
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rules;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\AvatarAsset;
|
||||
use App\Models\DefaultUserAsset;
|
||||
use App\Models\UserAsset;
|
||||
use App\Models\Username;
|
||||
use App\Models\User;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
|
||||
class RegisteredUserController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the registration view.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('web.auth.register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming registration request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'username' => ['required', 'string', 'min:3', 'max:20', 'regex:/^[a-zA-Z0-9]+[ _.-]?[a-zA-Z0-9]+$/i', 'unique:usernames'],
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||||
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
||||
], [
|
||||
'username.min' => 'Username can only be 3 to 20 characters long.',
|
||||
'username.max' => 'Username can only be 3 to 20 characters long.',
|
||||
'username.regex' => 'Username must be alphanumeric and cannot begin or end with a special character. (a-z, 0-9, dots, hyphens, spaces, and underscores are allowed)'
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return back()->withErrors($validator)->withInput();
|
||||
}
|
||||
|
||||
$user = User::create([
|
||||
'username' => $request->username,
|
||||
'email' => $request->email,
|
||||
'password' => Hash::make($request->password),
|
||||
]);
|
||||
Username::create([
|
||||
'username' => $user->username,
|
||||
'user_id' => $user->id
|
||||
]);
|
||||
|
||||
foreach(DefaultUserAsset::all() as $defaultAsset)
|
||||
{
|
||||
UserAsset::createSerialed($user->id, $defaultAsset->asset_id);
|
||||
|
||||
if($defaultAsset->wearing)
|
||||
{
|
||||
AvatarAsset::create([
|
||||
'owner_id' => $user->id,
|
||||
'asset_id' => $defaultAsset->asset_id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$user->redraw();
|
||||
|
||||
event(new Registered($user));
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web\Auth;
|
||||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Auth\Events\Verified;
|
||||
use Illuminate\Foundation\Auth\EmailVerificationRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class VerifyEmailController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mark the authenticated user's email address as verified.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Auth\EmailVerificationRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function __invoke(EmailVerificationRequest $request)
|
||||
{
|
||||
if ($request->user()->hasVerifiedEmail()) {
|
||||
return redirect()->intended(RouteServiceProvider::HOME);
|
||||
}
|
||||
|
||||
if ($request->user()->markEmailAsVerified()) {
|
||||
event(new Verified($request->user()));
|
||||
}
|
||||
|
||||
return redirect()->intended(RouteServiceProvider::HOME);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class AvatarController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('web.avatar.editor');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Helpers\GridHelper;
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\AvatarAsset;
|
||||
use App\Models\User;
|
||||
|
||||
class ClientAvatarController extends Controller
|
||||
{
|
||||
public function bodyColors(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'userId' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\User', 'id')
|
||||
]
|
||||
]);
|
||||
|
||||
if($validator->fails()) {
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
$user = User::where('id', $valid['userId'])->first();
|
||||
|
||||
if($user->hasActivePunishment() && $user->getPunishment()->isDeletion()) {
|
||||
$validator->errors()->add('id', 'User is moderated.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$document = simplexml_load_string(GridHelper::getBodyColorsXML());
|
||||
$bodyColors = $user->getBodyColors();
|
||||
|
||||
$document->xpath('//int[@name="HeadColor"]')[0][0] = $bodyColors->head;
|
||||
$document->xpath('//int[@name="TorsoColor"]')[0][0] = $bodyColors->torso;
|
||||
$document->xpath('//int[@name="LeftArmColor"]')[0][0] = $bodyColors->leftArm;
|
||||
$document->xpath('//int[@name="LeftLegColor"]')[0][0] = $bodyColors->leftLeg;
|
||||
$document->xpath('//int[@name="RightArmColor"]')[0][0] = $bodyColors->rightArm;
|
||||
$document->xpath('//int[@name="RightLegColor"]')[0][0] = $bodyColors->rightLeg;
|
||||
|
||||
return response($document->asXML())
|
||||
->header('Content-Type', 'application/xml');
|
||||
}
|
||||
|
||||
public function characterFetch(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'userId' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\User', 'id')
|
||||
]
|
||||
]);
|
||||
|
||||
if($validator->fails()) {
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
$user = User::where('id', $valid['userId'])->first();
|
||||
|
||||
if($user->hasActivePunishment() && $user->getPunishment()->isDeletion()) {
|
||||
$validator->errors()->add('id', 'User is moderated.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$charApp = '';
|
||||
$charApp .= route('client.bodyColors', ['userId' => $user->id]);
|
||||
|
||||
foreach($user->getWearing()->get() as $avatarAsset)
|
||||
{
|
||||
$charApp .= ';' . route('client.asset', ['id' => $avatarAsset->asset->id]);
|
||||
|
||||
if($avatarAsset->asset->assetTypeId == 19) // Gear
|
||||
$charApp .= '&equipped=1';
|
||||
}
|
||||
|
||||
return response($charApp)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\Helpers\GridHelper;
|
||||
use App\Helpers\ValidationHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetVersion;
|
||||
use App\Models\RobloxAsset;
|
||||
use App\Models\UserAsset;
|
||||
|
||||
class ClientController extends Controller
|
||||
{
|
||||
function assetRegularValidator()
|
||||
{
|
||||
return [
|
||||
'id' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\Asset', 'id')->where(function($query) {
|
||||
return $query->where('moderated', false)
|
||||
->where('approved', true);
|
||||
})
|
||||
],
|
||||
'version' => [
|
||||
'sometimes',
|
||||
'numeric'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
function assetVersionValidator()
|
||||
{
|
||||
return [
|
||||
'assetversionid' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\AssetVersion', 'id')
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
function userAssetValidator()
|
||||
{
|
||||
return [
|
||||
'userassetid' => [
|
||||
'required',
|
||||
Rule::exists('App\Models\UserAsset', 'id')
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
function asset(Request $request)
|
||||
{
|
||||
$reqData = array_change_key_case($request->all());
|
||||
$isVersionIdRequest = array_key_exists('assetversionid', $reqData);
|
||||
$isUserAssetIdRequest = array_key_exists('userassetid', $reqData);
|
||||
|
||||
$validatorRuleSet = 'assetRegularValidator';
|
||||
if($isVersionIdRequest)
|
||||
$validatorRuleSet = 'assetVersionValidator';
|
||||
elseif($isUserAssetIdRequest)
|
||||
$validatorRuleSet = 'userAssetValidator';
|
||||
|
||||
$validator = Validator::make($reqData, $this->{$validatorRuleSet}());
|
||||
|
||||
if($validator->fails())
|
||||
{
|
||||
$rbxAsset = RobloxAsset::where('robloxAssetId', $request->get('id'))->first();
|
||||
if($rbxAsset)
|
||||
return redirect()->route('client.asset', ['id' => $rbxAsset->localAssetId]);
|
||||
|
||||
return redirect('https://assetdelivery.roblox.com/v1/asset?id=' . ($request->get('id') ?: 0));//return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$valid = $validator->valid();
|
||||
$asset = null;
|
||||
|
||||
if($isVersionIdRequest) {
|
||||
$assetVersion = AssetVersion::where('id', $valid['assetversionid'])->first();
|
||||
$asset = $assetVersion->asset;
|
||||
|
||||
$valid['version'] = $assetVersion->localVersion;
|
||||
} elseif($isUserAssetIdRequest) {
|
||||
$userAsset = UserAsset::where('id', $valid['userassetid'])->first();
|
||||
$asset = $userAsset->asset;
|
||||
} else {
|
||||
$asset = Asset::where('id', $valid['id'])->first();
|
||||
}
|
||||
|
||||
if(!$isVersionIdRequest && !array_key_exists('version', $valid))
|
||||
$valid['version'] = 0;
|
||||
|
||||
if($asset == null) {
|
||||
$validator->errors()->add('version', 'Unknown asset' . ($isVersionIdRequest ? ' version' : null) . '.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
if(
|
||||
!($asset->onSale || (Auth::check() && Auth::user()->id == $asset->creatorId)) // not on sale and not the creator
|
||||
&&
|
||||
!($asset->copyable()) // asset isn't defaulted to open source
|
||||
&&
|
||||
!GridHelper::hasAllAccess() // not grid
|
||||
) {
|
||||
$validator->errors()->add('id', 'You do not have access to this asset.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
$contentHash = $asset->getContent($valid['version']);
|
||||
if(!$contentHash) {
|
||||
$validator->errors()->add('version', 'Unknown asset version.');
|
||||
return ValidationHelper::generateValidatorError($validator);
|
||||
}
|
||||
|
||||
return redirect(route('content', $contentHash));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
// for future reference http://web.archive.org/web/20080531065005id_/roblox.com/Game/PlaceLauncher.asmx?WSDL
|
||||
/*
|
||||
PlaceLauncher Status Key
|
||||
|
||||
0: "" (Retry for client, no string for MadStatus)
|
||||
1: "A server is loading the game..." (Retry for client)
|
||||
2: "The server is ready. Joining the game..."
|
||||
3: "Joining games is temporarily disabled while we upgrade. Please try again soon." (Displayed by MadStatus but results in an error for the client)
|
||||
4: "An error occurred. Please try again later." (Displayed by MadStatus but results in an error for the client)
|
||||
5: "The game you requested has ended." (Displayed by MadStatus but results in an error for the client)
|
||||
6: "The game you requested is currently full. Waiting for an opening..."
|
||||
7: "Roblox is updating. Please wait..." (Used by MadStatus)
|
||||
8: "Requesting a server" (Displayed before a request is sent to PlaceLauncher.ashx)
|
||||
|
||||
Place join status results:
|
||||
Waiting = 0
|
||||
Loading = 1
|
||||
Joining = 2
|
||||
Disabled = 3
|
||||
Error = 4
|
||||
GameEnded = 5
|
||||
GameFull = 6
|
||||
UserLeft = 10
|
||||
Restricted = 11
|
||||
*/
|
||||
|
||||
class ClientGameController extends Controller
|
||||
{
|
||||
public function placeLauncher(Request $request)
|
||||
{
|
||||
return response([
|
||||
'status' => 0,
|
||||
'authenticationUrl' => '',
|
||||
'authenticationTicket' => '',
|
||||
'joinScriptUrl' => ''
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class GamesController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('web.games.index');
|
||||
}
|
||||
|
||||
public function showGame(Request $request, Asset $asset, string $assetName = null)
|
||||
{
|
||||
$assetSlug = Str::slug($asset->name, '-');
|
||||
|
||||
if($asset->moderated)
|
||||
abort(404);
|
||||
|
||||
if($asset->assetTypeId != 9) // Place
|
||||
return redirect()->route('shop.asset', ['asset' => $asset->id, 'assetName' => $assetSlug]);
|
||||
|
||||
if ($assetName != $assetSlug)
|
||||
return redirect()->route('games.asset', ['asset' => $asset->id, 'assetName' => $assetSlug]);
|
||||
|
||||
return view('web.games.asset')->with([
|
||||
'title' => sprintf('%s by %s', $asset->universe->name, $asset->user->username),
|
||||
'asset' => $asset
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
public function landing()
|
||||
{
|
||||
return view('web.home.landing');
|
||||
}
|
||||
|
||||
public function dashboard()
|
||||
{
|
||||
return view('web.home.dashboard');
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue