This commit is contained in:
lbenedar
2026-04-02 18:37:30 +03:00
commit d5577f10d7
26 changed files with 1946 additions and 0 deletions

232
internal/foundry/foundry.go Normal file
View File

@@ -0,0 +1,232 @@
package foundry
import (
"errors"
"fmt"
"io"
"net/http"
"strconv"
"strings"
)
const (
authPath = "/auth"
licensePath = "/license"
joinPath = "/join"
playersPath = "/players"
setupPath = "/setup"
updatePath = "/update"
socketPath = "/socket.io"
)
var WsTypeData = map[string]string{
authPath: "getAuthData",
licensePath: "getAuthData",
joinPath: "getJoinData",
playersPath: "getPlayersData",
setupPath: "getSetupData",
updatePath: "getUpdateData",
}
type FoundryCode int
const (
WriterCode = FoundryCode(0)
ReaderCode = FoundryCode(1)
RespSessionData = "0"
RespPingCode = "2"
RespSessionId = "40"
RespCreateSessionCode = "42"
RespDataCode = "43"
ReqPongCode = "3"
ReqCreateSessionCode = "40"
ReqDataCode = "42"
)
var RequestCodes = []string{
RespSessionData,
RespPingCode,
RespSessionId,
RespCreateSessionCode,
RespDataCode,
}
var CodesRespToReq = map[string]string{
RespSessionData: ReqCreateSessionCode,
RespPingCode: ReqPongCode,
RespCreateSessionCode: ReqDataCode,
//ReqDataCode: RespCreateSessionCode,
}
type Foundry struct {
config foundry_config
sessionID string
isAuth bool
currPage string
ws *webSocketUtil
}
type foundry_config struct {
host string
}
func (foundry *Foundry) checkAuthRespAnswer(r io.Reader, respLength int) error {
authBody := make([]byte, respLength)
_, err := r.Read(authBody)
if err != nil && err != io.EOF {
return err
}
if !strings.Contains(string(authBody), "Admin authentication successful") {
return ErrorAuthPassWrong
}
foundry.isAuth = true
return nil
}
func (foundry *Foundry) getSessionTokenFromHeader(resp http.Header) (bool, error) {
setCookieHeader := resp.Get("Set-Cookie")
if setCookieHeader == "" {
return false, nil
}
for value := range strings.SplitSeq(setCookieHeader, ";") {
if strings.Contains(value, "session") {
sessionCookie := strings.Split(value, "=")
if len(sessionCookie) != 2 {
return false, ErrorSidWrongFormat
}
foundry.sessionID = sessionCookie[1]
return true, nil
}
}
return false, nil
}
func (foundry *Foundry) Authenticate(password string) error {
if foundry.sessionID == "" {
err := foundry.setUpSessionId()
if err != nil {
return err
}
}
req, err := createAuthRequest(foundry.config.host, foundry.sessionID, password)
if err != nil {
return err
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
contentLen, err := strconv.Atoi(resp.Header.Get("Content-Length"))
if err != nil {
return err
}
return foundry.checkAuthRespAnswer(resp.Body, contentLen)
}
func (foundry *Foundry) StartListen() error {
wsChannels := foundry.ws.InitWsChannels()
defer wsChannels.Close()
go foundry.ListenAndServeWS()
var err error
for {
select {
case err = <-wsChannels.Err():
var foundryErr *FoundryError
if errors.As(err, &foundryErr) {
if foundryErr.IsFatal {
foundry.CloseWebSocketConn()
return foundryErr
}
}
case <-wsChannels.Done():
foundry.CloseWebSocketConn()
return ListenIsDone
}
}
}
func (foundry *Foundry) CloseWebSocketConn() {
foundry.ws.wsConn.Close()
}
func (foundry *Foundry) ListenAndServeWS() {
go foundry.ws.ListenWebSocket()
foundry.ws.ServeWebSocket()
}
func (foundry *Foundry) CreateWSMessageByPage(page string) *wsMessage {
msgToSend := &wsMessage{code: CodesRespToReq[RespCreateSessionCode], id: foundry.ws.currWsId, msgJson: fmt.Sprintf("[\"%s\"]", WsTypeData[page])}
foundry.ws.currWsId++
fmt.Printf("Msg: %s\n", msgToSend.toString())
return msgToSend
}
func (foundry *Foundry) HandleWebsocketRequest(msg *wsMessage) ([]byte, error) {
return foundry.ws.HandleWebsocketRequest(msg)
}
func NewFoundry(host string) (*Foundry, error) {
foundry := &Foundry{config: foundry_config{host: host}, isAuth: false, currPage: authPath, ws: NewWebSocketUtil()}
err := foundry.setUpSessionId()
if err != nil {
return nil, err
}
return foundry, nil
}
// /**
// * Poll the server to see if a World has become active, and automatically refresh if so.
// * @returns {Promise<void>}
// */
// async #pollActive() {
// const poll = () => {
// const status = foundry.utils.getRoute("/api/status");
// this.#activePollState.last = Date.now();
// this.#activePollState.polling = foundry.utils.fetchJsonWithTimeout(status, {}, {
// timeoutMs: 10000
// }).catch(() => {});
// this.#pollActive();
// };
// func (foundry *Foundry) SendPageDataRequest(page string) error {
// msgToSend := &wsComm{code: CodesRespToReq[RespCreateSessionCode], id: foundry.ws.currWsId, msgJson: fmt.Sprintf("[\"%s\"]", WsTypeData[page])}
// foundry.ws.currWsId++
// log.Printf("send: %s\n", msgToSend.toString())
// return foundry.ws.wsConn.WriteMessage(websocket.TextMessage, msgToSend.toByteSlice())
// }
// func (foundry *Foundry) setUpWebSocketConnection() error {
// err := foundry.wsConn.WriteMessage(websocket.TextMessage, []byte("40"))
// if err != nil {
// return err
// }
// return nil
// }
// func (foundry *Foundry) sendPageDataRequest(page string) error {
// msgToSend := &wsComm{code: CodesRespToReq[RespCreateSessionCode], id: foundry.ws.currWsId, msgJson: fmt.Sprintf("[\"%s\"]", WsTypeData[page])}
// foundry.ws.currWsId++
// log.Printf("send: %s\n", msgToSend.toString())
// return foundry.ws.wsConn.WriteMessage(websocket.TextMessage, msgToSend.toByteSlice())
// }