mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-12 15:04:38 +01:00
initial commit
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,4 +7,5 @@ savedata/*/
|
||||
*.exe
|
||||
*.lnk
|
||||
*.bat
|
||||
/docker/db-data
|
||||
/docker/db-data
|
||||
sreenshots/*
|
||||
@@ -9,7 +9,12 @@
|
||||
],
|
||||
"PatchServerManifest": "",
|
||||
"PatchServerFile": "",
|
||||
"ScreenshotAPIURL": "",
|
||||
"Screenshots":{
|
||||
"Enabled":true,
|
||||
"Host":"127.0.0.1",
|
||||
"Port":8080,
|
||||
"OutputDir":"screenshots"
|
||||
},
|
||||
"DeleteOnSaveCorruption": false,
|
||||
"ClientMode": "ZZ",
|
||||
"QuestCacheExpiry": 300,
|
||||
|
||||
@@ -75,7 +75,6 @@ type Config struct {
|
||||
LoginNotices []string // MHFML string of the login notices displayed
|
||||
PatchServerManifest string // Manifest patch server override
|
||||
PatchServerFile string // File patch server override
|
||||
ScreenshotAPIURL string // Destination for screenshots uploaded to BBS
|
||||
DeleteOnSaveCorruption bool // Attempts to save corrupted data will flag the save for deletion
|
||||
ClientMode string
|
||||
RealClientMode Mode
|
||||
@@ -87,16 +86,18 @@ type Config struct {
|
||||
EarthID int32
|
||||
EarthMonsters []int32
|
||||
SaveDumps SaveDumpOptions
|
||||
DebugOptions DebugOptions
|
||||
GameplayOptions GameplayOptions
|
||||
Discord Discord
|
||||
Commands []Command
|
||||
Courses []Course
|
||||
Database Database
|
||||
Sign Sign
|
||||
SignV2 SignV2
|
||||
Channel Channel
|
||||
Entrance Entrance
|
||||
Screenshots ScreenshotsOptions
|
||||
|
||||
DebugOptions DebugOptions
|
||||
GameplayOptions GameplayOptions
|
||||
Discord Discord
|
||||
Commands []Command
|
||||
Courses []Course
|
||||
Database Database
|
||||
Sign Sign
|
||||
SignV2 SignV2
|
||||
Channel Channel
|
||||
Entrance Entrance
|
||||
}
|
||||
|
||||
type SaveDumpOptions struct {
|
||||
@@ -105,6 +106,13 @@ type SaveDumpOptions struct {
|
||||
OutputDir string
|
||||
}
|
||||
|
||||
type ScreenshotsOptions struct {
|
||||
Enabled bool
|
||||
Host string // Destination for screenshots uploaded to BBS
|
||||
Port uint32 // Port for screenshots API
|
||||
OutputDir string
|
||||
}
|
||||
|
||||
// DebugOptions holds various debug/temporary options for use while developing Erupe.
|
||||
type DebugOptions struct {
|
||||
CleanDB bool // Automatically wipes the DB on server reset.
|
||||
|
||||
13
schemas/patch-schema/screenshots.sql
Normal file
13
schemas/patch-schema/screenshots.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE public.screenshots
|
||||
(
|
||||
id serial PRIMARY KEY,
|
||||
article_id TEXT NOT NULL,
|
||||
discord_message_id TEXT,
|
||||
char_id integer NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
discord_img_url TEXT,
|
||||
);
|
||||
END;
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func handleMsgMhfGetBbsUserStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
//Post Screenshot pauses till this succeedes
|
||||
pkt := p.(*mhfpacket.MsgMhfGetBbsUserStatus)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(200)
|
||||
@@ -32,10 +33,36 @@ func handleMsgMhfApplyBbsArticle(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
articleToken := token.Generate(40)
|
||||
bf.WriteUint32(200)
|
||||
bf.WriteUint32(80)
|
||||
bf.WriteUint32(s.server.erupeConfig.Screenshots.Port)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteBytes(stringsupport.PaddedString(articleToken, 64, false))
|
||||
bf.WriteBytes(stringsupport.PaddedString(s.server.erupeConfig.ScreenshotAPIURL, 64, false))
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
bf.WriteBytes(stringsupport.PaddedString(s.server.erupeConfig.Screenshots.Host, 64, false))
|
||||
|
||||
if s.server.erupeConfig.SaveDumps.Enabled && s.server.erupeConfig.Discord.Enabled {
|
||||
messageId := s.server.DiscordScreenShotSend(pkt.Name, pkt.Title, pkt.Description) // TODO: send and get back message id store in db
|
||||
|
||||
_, err := s.server.db.Exec("INSERT INTO public.screenshots (article_id,discord_message_id,char_id,title,description) VALUES ($1,$2,$3,$4,$5)", articleToken, messageId, s.charID, pkt.Title, pkt.Description)
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
s.server.BroadcastChatMessage("Screenshot has been sent to discord")
|
||||
|
||||
}
|
||||
|
||||
} else if s.server.erupeConfig.SaveDumps.Enabled {
|
||||
_, err := s.server.db.Exec("INSERT INTO public.screenshots (article_id,char_id,title,description) VALUES ($1,$2,$3,$4)", articleToken, s.charID, pkt.Title, pkt.Description)
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
s.server.BroadcastChatMessage("Screenshot has been sent to server")
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
|
||||
}
|
||||
} else {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.server.BroadcastChatMessage("No destination for screenshots have been configured by the host")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,6 +367,15 @@ func (s *Server) DiscordChannelSend(charName string, content string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) DiscordScreenShotSend(charName string, title string, description string) string {
|
||||
if s.erupeConfig.Discord.Enabled && s.discordBot != nil {
|
||||
message := fmt.Sprintf("**%s**: %s - %s", charName, title, description)
|
||||
mesageId, _ := s.discordBot.RealtimeChannelSend(message)
|
||||
return mesageId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *Server) FindSessionByCharID(charID uint32) *Session {
|
||||
for _, c := range s.Channels {
|
||||
for _, session := range c.sessions {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package discordbot
|
||||
|
||||
import (
|
||||
"erupe-ce/config"
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"regexp"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"go.uber.org/zap"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var Commands = []*discordgo.ApplicationCommand{
|
||||
@@ -104,14 +106,14 @@ func (bot *DiscordBot) NormalizeDiscordMessage(message string) string {
|
||||
return result
|
||||
}
|
||||
|
||||
func (bot *DiscordBot) RealtimeChannelSend(message string) (err error) {
|
||||
func (bot *DiscordBot) RealtimeChannelSend(message string) (messageId string, err error) {
|
||||
if bot.RelayChannel == nil {
|
||||
return
|
||||
return "", errors.New("RelayChannel is nil")
|
||||
}
|
||||
|
||||
_, err = bot.Session.ChannelMessageSend(bot.RelayChannel.ID, message)
|
||||
msg, err := bot.Session.ChannelMessageSend(bot.RelayChannel.ID, message)
|
||||
|
||||
return
|
||||
return msg.ID, err
|
||||
}
|
||||
|
||||
func ReplaceTextAll(text string, regex *regexp.Regexp, handler func(input string) string) string {
|
||||
|
||||
@@ -6,7 +6,12 @@ import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/server/channelserver"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -286,3 +291,66 @@ func (s *Server) ExportSave(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(save)
|
||||
}
|
||||
|
||||
func (s *Server) ScreenShot(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.erupeConfig.SaveDumps.Enabled {
|
||||
http.Error(w, "Screenshots not enabled in Config", http.StatusBadRequest)
|
||||
|
||||
return
|
||||
} else {
|
||||
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
// Get File from Request
|
||||
file, _, err := r.FormFile("img")
|
||||
if err != nil {
|
||||
http.Error(w, "No valid file uploaded", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
token := r.FormValue("token")
|
||||
if token == "" {
|
||||
http.Error(w, "Token not specified cannot continue", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate file
|
||||
img, _, err := image.Decode(file)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid image file", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
dir := filepath.Join(s.erupeConfig.Screenshots.OutputDir)
|
||||
path := filepath.Join(s.erupeConfig.Screenshots.OutputDir, fmt.Sprintf("%s.jpg", token))
|
||||
_, err = os.Stat(dir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = os.MkdirAll(dir, os.ModePerm)
|
||||
if err != nil {
|
||||
s.logger.Error("Error writing screenshot, could not create folder")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
s.logger.Error("Error writing screenshot")
|
||||
return
|
||||
}
|
||||
}
|
||||
// Create or open the output file
|
||||
outputFile, err := os.Create(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer outputFile.Close()
|
||||
|
||||
// Encode the image and write it to the file
|
||||
err = jpeg.Encode(outputFile, img, &jpeg.Options{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err != nil {
|
||||
s.logger.Error("Error writing screenshot, could not write file", zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package signv2server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"erupe-ce/config"
|
||||
_config "erupe-ce/config"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -52,6 +52,7 @@ func (s *Server) Start() error {
|
||||
r.HandleFunc("/character/create", s.CreateCharacter)
|
||||
r.HandleFunc("/character/delete", s.DeleteCharacter)
|
||||
r.HandleFunc("/character/export", s.ExportSave)
|
||||
r.HandleFunc("/api/ss/bbs/upload.php", s.ScreenShot)
|
||||
handler := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"}))(r)
|
||||
s.httpServer.Handler = handlers.LoggingHandler(os.Stdout, handler)
|
||||
s.httpServer.Addr = fmt.Sprintf(":%d", s.erupeConfig.SignV2.Port)
|
||||
|
||||
Reference in New Issue
Block a user