This commit is contained in:
Dev
2025-09-12 16:33:52 +03:00
commit d2314f6934
9 changed files with 939 additions and 0 deletions

223
internal/server/server.go Normal file
View File

@@ -0,0 +1,223 @@
package server
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"github.com/gorilla/mux"
"github.com/iwasforcedtobehere/gomeme/internal/meme"
)
// Server represents our meme server
type Server struct {
generator *meme.Generator
}
// New creates a new server instance
func New() *Server {
return &Server{
generator: meme.NewGenerator(),
}
}
// Routes sets up all the HTTP routes
func (s *Server) Routes() http.Handler {
r := mux.NewRouter()
// Static files
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("web/static/"))))
// Web interface
r.HandleFunc("/", s.homeHandler).Methods("GET")
r.HandleFunc("/generate", s.generateWebHandler).Methods("POST")
// API endpoints
api := r.PathPrefix("/api/v1").Subrouter()
api.HandleFunc("/memes", s.generateAPIHandler).Methods("POST")
api.HandleFunc("/memes/{id}", s.getMemeHandler).Methods("GET")
api.HandleFunc("/templates", s.getTemplatesHandler).Methods("GET")
api.HandleFunc("/health", s.healthHandler).Methods("GET")
return r
}
// homeHandler serves the main page
func (s *Server) homeHandler(w http.ResponseWriter, r *http.Request) {
html := `<!DOCTYPE html>
<html>
<head>
<title>GoMeme - Because Manual Meme Making is for Peasants</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body { font-family: 'Comic Sans MS', cursive; background: linear-gradient(45deg, #ff6b6b, #4ecdc4); margin: 0; padding: 20px; }
.container { max-width: 800px; margin: 0 auto; background: white; border-radius: 15px; padding: 30px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); }
h1 { color: #333; text-align: center; font-size: 2.5em; margin-bottom: 10px; }
.subtitle { text-align: center; color: #666; font-size: 1.2em; margin-bottom: 30px; }
.form-group { margin-bottom: 20px; }
label { display: block; margin-bottom: 5px; font-weight: bold; color: #333; }
input, select, textarea { width: 100%; padding: 10px; border: 2px solid #ddd; border-radius: 5px; font-size: 16px; }
button { background: #ff6b6b; color: white; padding: 15px 30px; border: none; border-radius: 5px; font-size: 18px; cursor: pointer; width: 100%; }
button:hover { background: #ff5252; }
.footer { text-align: center; margin-top: 30px; color: #666; font-style: italic; }
</style>
</head>
<body>
<div class="container">
<h1>🎭 GoMeme Generator</h1>
<p class="subtitle">Automated meme production because who has time for manual labor?</p>
<form action="/generate" method="POST">
<div class="form-group">
<label for="template">Meme Template:</label>
<select id="template" name="template" required>
<option value="drake">Drake Pointing</option>
<option value="distracted">Distracted Boyfriend</option>
<option value="woman_yelling">Woman Yelling at Cat</option>
<option value="change_my_mind">Change My Mind</option>
<option value="this_is_fine">This is Fine</option>
</select>
</div>
<div class="form-group">
<label for="top_text">Top Text:</label>
<textarea id="top_text" name="top_text" rows="2" placeholder="Enter your brilliant top text here..."></textarea>
</div>
<div class="form-group">
<label for="bottom_text">Bottom Text:</label>
<textarea id="bottom_text" name="bottom_text" rows="2" placeholder="Enter your even more brilliant bottom text here..."></textarea>
</div>
<button type="submit">Generate This Fucking Masterpiece</button>
</form>
<div class="footer">
<p>Built with Go, goroutines, and a healthy dose of sarcasm 🚀</p>
<p><a href="/api/v1/health" style="color: #666;">API Health Check</a> | <a href="/api/v1/templates" style="color: #666;">Available Templates</a></p>
</div>
</div>
</body>
</html>`
w.Header().Set("Content-Type", "text/html")
fmt.Fprint(w, html)
}
// generateWebHandler handles web form submissions
func (s *Server) generateWebHandler(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
http.Error(w, "Failed to parse form", http.StatusBadRequest)
return
}
req := meme.GenerateRequest{
Template: r.FormValue("template"),
TopText: r.FormValue("top_text"),
BottomText: r.FormValue("bottom_text"),
}
result, err := s.generator.Generate(req)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to generate meme: %v", err), http.StatusInternalServerError)
return
}
// Return HTML with the generated meme
html := fmt.Sprintf(`<!DOCTYPE html>
<html>
<head>
<title>Your Meme is Ready!</title>
<meta charset="UTF-8">
<style>
body { font-family: 'Comic Sans MS', cursive; background: linear-gradient(45deg, #ff6b6b, #4ecdc4); margin: 0; padding: 20px; text-align: center; }
.container { max-width: 600px; margin: 0 auto; background: white; border-radius: 15px; padding: 30px; }
img { max-width: 100%%; border-radius: 10px; box-shadow: 0 5px 15px rgba(0,0,0,0.3); }
.buttons { margin-top: 20px; }
.btn { display: inline-block; padding: 10px 20px; margin: 5px; background: #4ecdc4; color: white; text-decoration: none; border-radius: 5px; }
.btn:hover { background: #26a69a; }
</style>
</head>
<body>
<div class="container">
<h1>🎉 Your Meme is Ready!</h1>
<img src="/static/generated/%s" alt="Generated Meme">
<div class="buttons">
<a href="/" class="btn">Create Another Masterpiece</a>
<a href="/static/generated/%s" class="btn" download>Download This Beauty</a>
</div>
<p><strong>Share URL:</strong> <code>%s</code></p>
</div>
</body>
</html>`, result.Filename, result.Filename, result.ShareURL)
w.Header().Set("Content-Type", "text/html")
fmt.Fprint(w, html)
}
// generateAPIHandler handles API meme generation requests
func (s *Server) generateAPIHandler(w http.ResponseWriter, r *http.Request) {
var req meme.GenerateRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}
result, err := s.generator.Generate(req)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to generate meme: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(result)
}
// getMemeHandler retrieves a specific meme by ID
func (s *Server) getMemeHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
// Convert string ID to int for demo purposes
memeID, err := strconv.Atoi(id)
if err != nil {
http.Error(w, "Invalid meme ID", http.StatusBadRequest)
return
}
meme, err := s.generator.GetMeme(memeID)
if err != nil {
http.Error(w, "Meme not found", http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(meme)
}
// getTemplatesHandler returns available meme templates
func (s *Server) getTemplatesHandler(w http.ResponseWriter, r *http.Request) {
templates := s.generator.GetTemplates()
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"templates": templates,
"count": len(templates),
})
}
// healthHandler provides health check endpoint
func (s *Server) healthHandler(w http.ResponseWriter, r *http.Request) {
response := map[string]interface{}{
"status": "healthy",
"message": "GoMeme is alive and ready to generate some fucking awesome memes!",
"timestamp": "2025-09-12T00:00:00Z",
"version": "1.0.0",
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}