Skip to content

Commit 35e1774

Browse files
committed
Add publishsave
1 parent bbc8405 commit 35e1774

7 files changed

Lines changed: 209 additions & 11 deletions

File tree

cloudbox.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/flatgrassdotnet/cloudbox/api/news"
3030
"github.com/flatgrassdotnet/cloudbox/api/packages"
3131
"github.com/flatgrassdotnet/cloudbox/db"
32+
"github.com/flatgrassdotnet/cloudbox/ingame/publishsave"
3233
"github.com/flatgrassdotnet/cloudbox/ingame/stats"
3334
"github.com/flatgrassdotnet/cloudbox/ingame/toyboxapi"
3435
"github.com/flatgrassdotnet/cloudbox/utils"
@@ -61,20 +62,38 @@ func main() {
6162
http.HandleFunc("GET /packages/get", packages.Get)
6263
http.HandleFunc("GET /packages/getscript", packages.GetScript)
6364
http.HandleFunc("GET /packages/getgma", packages.GetGMA)
64-
http.HandleFunc("GET /packages/publishsave", packages.PublishSave)
6565
http.HandleFunc("GET /content/get", content.Get)
6666
http.HandleFunc("GET /content/getzip", content.GetZIP)
6767
http.HandleFunc("GET /content/fastdl", content.FastDL)
6868

6969
// stats.garrysmod.com
70-
http.HandleFunc("GET /API/mapload_001/", stats.MapLoad)
70+
http.HandleFunc("GET stats.garrysmod.com/API/mapload_001/", stats.MapLoad)
7171

7272
// toyboxapi.garrysmod.com
73-
http.HandleFunc("POST /auth_003/", toyboxapi.Auth)
74-
http.HandleFunc("GET /error_003/", toyboxapi.Error)
75-
http.HandleFunc("GET /getinstall_003/", toyboxapi.GetPackage)
76-
http.HandleFunc("GET /getscript_003/", toyboxapi.GetPackage)
77-
http.HandleFunc("POST /upload_003/", toyboxapi.Upload)
73+
// auth
74+
http.HandleFunc("GET toyboxapi.garrysmod.com/auth_001/", toyboxapi.Auth)
75+
http.HandleFunc("POST toyboxapi.garrysmod.com/auth_002/", toyboxapi.Auth)
76+
http.HandleFunc("POST toyboxapi.garrysmod.com/auth_003/", toyboxapi.Auth)
77+
78+
// getinstall
79+
http.HandleFunc("GET toyboxapi.garrysmod.com/getinstall_001/", toyboxapi.GetPackage)
80+
http.HandleFunc("GET toyboxapi.garrysmod.com/getinstall_003/", toyboxapi.GetPackage)
81+
82+
// getscript
83+
http.HandleFunc("GET toyboxapi.garrysmod.com/getscript_001/", toyboxapi.GetPackage)
84+
http.HandleFunc("GET toyboxapi.garrysmod.com/getscript_003/", toyboxapi.GetPackage)
85+
86+
// upload
87+
http.HandleFunc("POST toyboxapi.garrysmod.com/upload_001/", toyboxapi.Upload)
88+
http.HandleFunc("POST toyboxapi.garrysmod.com/upload_003/", toyboxapi.Upload)
89+
90+
// error
91+
http.HandleFunc("GET toyboxapi.garrysmod.com/error_001/", toyboxapi.Error)
92+
http.HandleFunc("GET toyboxapi.garrysmod.com/error_003/", toyboxapi.Error)
93+
94+
// publishsave
95+
http.HandleFunc("GET toyboxapi.garrysmod.com/publishsave_002/", publishsave.Save) // virtual
96+
http.HandleFunc("POST toyboxapi.garrysmod.com/publishsave_002/", publishsave.Publish) // virtual
7897

7998
err = http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)
8099
if err != nil {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<html>
2+
<head>
3+
{{template "style"}}
4+
</head>
5+
<body>
6+
<div id="container">
7+
<h2>Published!</h2>
8+
<row style="font-size: 12px;">
9+
Your saved game has been published.<br>
10+
You can manage your saved games out of game by visiting http://toybox.garrysmod.com in your favourite browser.<br>
11+
(You can close this window)
12+
</row>
13+
</div>
14+
</body>
15+
</html>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<html>
2+
<head>
3+
{{template "style"}}
4+
</head>
5+
<body>
6+
<div id="container">
7+
<h2>Publish Saved Game</h2>
8+
<form action="/API/publishsave_002/?id={{.ID}}&sid={{.SID}}" method="post">
9+
<div class="row">
10+
<label for="name">Name:</label>
11+
<input type="text" name="name" id="name" required>
12+
</div>
13+
<div class="row">
14+
<label>Map:</label>
15+
<input type="text" value="{{.Map}}" disabled>
16+
</div>
17+
<div class="row">
18+
<label for="desc">Description:</label>
19+
<textarea name="desc" id="desc" required></textarea>
20+
</div>
21+
<div class="row">
22+
<label>Category:</label>
23+
<fieldset>
24+
<label><input type="radio" name="cat" value="1" checked> Uncategorized</label>
25+
<label><input type="radio" name="cat" value="2"> Fun</label>
26+
<label><input type="radio" name="cat" value="3"> Construction</label>
27+
<label><input type="radio" name="cat" value="4"> Scene</label>
28+
<label><input type="radio" name="cat" value="5"> Assault Course</label>
29+
<label><input type="radio" name="cat" value="6"> Gun Fight</label>
30+
</fieldset>
31+
</div>
32+
<div class="row">
33+
<label></label>
34+
<button>Publish Saved Game</button>
35+
</div>
36+
</form>
37+
</div>
38+
</body>
39+
</html>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{{define "style"}}<style type="text/css">body {background-color: #222; margin: 15px; font-family: Helvetica, sans-serif;}
2+
3+
#container {background-color: white; border-radius: 8px; padding: 25px; color: #333;}
4+
5+
h2 {margin-top: 10px;}
6+
7+
/* row */
8+
.row {display: -webkit-box; margin-top: 5px; margin-right: 120px;}
9+
10+
/* all row cells */
11+
.row > * {display: block; box-sizing: border-box;}
12+
13+
/* left cell (label) */
14+
.row > label {width: 160px; text-align: right; font-size: 12px; font-weight: bold; padding-right: 10px; padding-top: 3px;}
15+
16+
/* right cell (form input) */
17+
.row > label + * {-webkit-box-flex: 1; font-size: 13px;}
18+
19+
input[type="text"], textarea, fieldset {padding: 3px 5px; border: 2px solid #aaa; border-radius: 3px; background-color: #fafafa; margin: 0;}
20+
textarea {min-height: 70px;}
21+
22+
input[type="text"]:focus, textarea:focus {background-color: #ffa; border-color: #fb9; outline: none;}
23+
24+
input[type="text"]:disabled, textarea:disabled {opacity: 0.8;}
25+
26+
fieldset {-webkit-box-flex: 0 !important; padding-top: 8px; padding-bottom: 8px;}
27+
fieldset label {display: block; padding-right: 8px;}
28+
29+
button {-webkit-box-flex: 0 !important; margin: 0 auto; margin-top: 20px; padding: 5px 20px; font-size: 16px !important; font-weight:bold;}</style>{{end}}
Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,29 @@
1-
package packages
1+
/*
2+
cloudbox - the toybox server emulator
3+
Copyright (C) 2024-2025 patapancakes <[email protected]>
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Affero General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Affero General Public License for more details.
14+
15+
You should have received a copy of the GNU Affero General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
package publishsave
220

321
import (
422
"bytes"
23+
_ "embed"
524
"encoding/base64"
625
"fmt"
26+
"html/template"
727
"image/png"
828
"net/http"
929
"os"
@@ -16,7 +36,15 @@ import (
1636
"github.com/flatgrassdotnet/cloudbox/utils"
1737
)
1838

19-
func PublishSave(w http.ResponseWriter, r *http.Request) {
39+
var tp = template.Must(template.New("publish.html").ParseGlob("data/templates/publishsave/*.html"))
40+
41+
func Publish(w http.ResponseWriter, r *http.Request) {
42+
err := r.ParseForm()
43+
if err != nil {
44+
utils.WriteError(w, r, fmt.Sprintf("failed to parse form data: %s", err))
45+
return
46+
}
47+
2048
id, err := strconv.Atoi(r.URL.Query().Get("id"))
2149
if err != nil {
2250
utils.WriteError(w, r, fmt.Sprintf("failed to parse id value: %s", err))
@@ -36,7 +64,7 @@ func PublishSave(w http.ResponseWriter, r *http.Request) {
3664

3765
desc := r.URL.Query().Get("desc")
3866

39-
ticket, err := base64.StdEncoding.DecodeString(r.URL.Query().Get("ticket"))
67+
ticket, err := base64.StdEncoding.DecodeString(r.Header.Get("TICKET"))
4068
if err != nil {
4169
utils.WriteError(w, r, fmt.Sprintf("failed to decode ticket value: %s", err))
4270
return
@@ -112,6 +140,12 @@ func PublishSave(w http.ResponseWriter, r *http.Request) {
112140
return
113141
}
114142

143+
err = tp.Execute(w, nil)
144+
if err != nil {
145+
utils.WriteError(w, r, fmt.Sprintf("failed to execute template: %s", err))
146+
return
147+
}
148+
115149
// webhook related
116150
s, err := utils.GetPlayerSummaries(steamid)
117151
if err != nil {

ingame/publishsave/save.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
cloudbox - the toybox server emulator
3+
Copyright (C) 2024-2025 patapancakes <[email protected]>
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Affero General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Affero General Public License for more details.
14+
15+
You should have received a copy of the GNU Affero General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
package publishsave
20+
21+
import (
22+
_ "embed"
23+
"fmt"
24+
"html/template"
25+
"net/http"
26+
"strconv"
27+
28+
"github.com/flatgrassdotnet/cloudbox/utils"
29+
)
30+
31+
type SaveData struct {
32+
ID int
33+
SID int
34+
Map string
35+
}
36+
37+
var ts = template.Must(template.New("save.html").ParseGlob("data/templates/publishsave/*.html"))
38+
39+
func Save(w http.ResponseWriter, r *http.Request) {
40+
sd := SaveData{
41+
Map: r.Header.Get("MAP"),
42+
}
43+
44+
var err error
45+
sd.ID, err = strconv.Atoi(r.URL.Query().Get("id"))
46+
if err != nil {
47+
utils.WriteError(w, r, fmt.Sprintf("failed to parse id value: %s", err))
48+
return
49+
}
50+
51+
sd.SID, err = strconv.Atoi(r.URL.Query().Get("sid"))
52+
if err != nil {
53+
utils.WriteError(w, r, fmt.Sprintf("failed to parse sid value: %s", err))
54+
return
55+
}
56+
57+
err = ts.Execute(w, sd)
58+
if err != nil {
59+
utils.WriteError(w, r, fmt.Sprintf("failed to execute template: %s", err))
60+
return
61+
}
62+
}

ingame/toyboxapi/upload.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func Upload(w http.ResponseWriter, r *http.Request) {
5252

5353
// includes
5454
var includes []int
55-
if r.URL.Query().Has("inc") {
55+
if r.URL.Query().Get("inc") != "" {
5656
incs, err := csv.NewReader(bytes.NewReader([]byte(r.URL.Query().Get("inc")))).Read()
5757
if err != nil {
5858
utils.WriteError(w, r, fmt.Sprintf("failed to decode inc: %s", err))

0 commit comments

Comments
 (0)