@@ -3,12 +3,15 @@ package main
33import (
44 "encoding/json"
55 "fmt"
6+ "image"
67 "io/ioutil"
78 "log"
89 "net/http"
910 "os"
1011 "path/filepath"
1112 "strings"
13+
14+ "github.com/disintegration/imaging"
1215)
1316
1417type ShortcodeConfig struct {
@@ -21,10 +24,19 @@ type ServerConfig struct {
2124 ShowURLOnStart bool `json:"showURLOnStart"`
2225 GermanFolder string `json:"germanFolder"`
2326 EnglishFolder string `json:"englishFolder"`
27+ MediaFolder string `json:"mediaFolder"`
28+ AssetFolder string `json:"assetFolder"`
29+ ImageResize struct {
30+ Method string `json:"method"`
31+ MaxWidth int `json:"maxWidth"`
32+ } `json:"imageResize"`
33+ ThumbnailResize struct {
34+ Method string `json:"method"`
35+ MaxWidth int `json:"maxWidth"`
36+ } `json:"thumbnailResize"`
2437}
2538
2639type Config struct {
27- // Shortcodes ShortcodeConfig `json:"shortcodes"`
2840 Shortcodes map [string ]string `json:"shortcodes"`
2941 Icons map [string ]string `json:"icons"`
3042 Server ServerConfig `json:"server"`
@@ -36,25 +48,17 @@ func main() {
3648 // Load configuration
3749 loadConfig ()
3850
39- port := config .Server .Port
40-
4151 // Serve static files from the "static" directory
4252 fs := http .FileServer (http .Dir ("static" ))
4353 http .Handle ("/" , fs )
4454
45- // Start the server on localhost with the specified port
46- address := fmt .Sprintf ("http://localhost:%d" , port )
47- fmt .Printf ("Starting server at %s\n " , address )
48- err := http .ListenAndServe (address , nil )
49- if err != nil {
50- fmt .Printf ("Error starting server: %s\n " , err )
51- }
52-
5355 // API endpoints
5456 http .HandleFunc ("/api/config" , handleConfig )
5557 http .HandleFunc ("/api/save" , handleSave )
5658 http .HandleFunc ("/api/load" , handleLoad )
5759 http .HandleFunc ("/api/list" , handleList )
60+ http .HandleFunc ("/api/media-list" , handleMediaList )
61+ http .HandleFunc ("/api/process-media" , handleProcessMedia )
5862
5963 // Determine the address to listen on
6064 addr := fmt .Sprintf (":%d" , config .Server .Port )
@@ -66,6 +70,7 @@ func main() {
6670 log .Printf ("Server starting on port %d" , config .Server .Port )
6771 }
6872
73+ // Start the server
6974 log .Fatal (http .ListenAndServe (addr , nil ))
7075}
7176
@@ -92,14 +97,17 @@ func loadConfig() {
9297 }
9398
9499 // Convert relative paths to absolute paths
95- absPath , err := filepath .Abs (config .Server .GermanFolder )
96- if err = = nil {
97- config . Server . GermanFolder = absPath
100+ absGermanFolder , err := filepath .Abs (config .Server .GermanFolder )
101+ if err ! = nil {
102+ log . Fatalf ( "Error converting relative path to absolute path for German folder: %v" , err )
98103 }
99- absPath , err = filepath .Abs (config .Server .EnglishFolder )
100- if err == nil {
101- config .Server .EnglishFolder = absPath
104+ config .Server .GermanFolder = absGermanFolder
105+
106+ absEnglishFolder , err := filepath .Abs (config .Server .EnglishFolder )
107+ if err != nil {
108+ log .Fatalf ("Error converting relative path to absolute path for English folder: %v" , err )
102109 }
110+ config .Server .EnglishFolder = absEnglishFolder
103111}
104112
105113func handleConfig (w http.ResponseWriter , r * http.Request ) {
@@ -181,9 +189,6 @@ func handleList(w http.ResponseWriter, r *http.Request) {
181189func listFiles (dir string ) ([]string , error ) {
182190 var files []string
183191 err := filepath .Walk (dir , func (path string , info os.FileInfo , err error ) error {
184- if err != nil {
185- return err
186- }
187192 if ! info .IsDir () && strings .HasSuffix (info .Name (), ".md" ) {
188193 relPath , err := filepath .Rel (dir , path )
189194 if err != nil {
@@ -193,7 +198,10 @@ func listFiles(dir string) ([]string, error) {
193198 }
194199 return nil
195200 })
196- return files , err
201+ if err != nil {
202+ return nil , err
203+ }
204+ return files , nil
197205}
198206
199207func getFullPath (filename string ) string {
@@ -212,3 +220,85 @@ func getFullPath(filename string) string {
212220 return filename
213221 }
214222}
223+
224+ func handleMediaList (w http.ResponseWriter , r * http.Request ) {
225+ files , err := ioutil .ReadDir (config .Server .MediaFolder )
226+ if err != nil {
227+ http .Error (w , "Error reading media directory" , http .StatusInternalServerError )
228+ return
229+ }
230+
231+ var mediaFiles []string
232+ for _ , file := range files {
233+ if ! file .IsDir () {
234+ mediaFiles = append (mediaFiles , file .Name ())
235+ }
236+ }
237+
238+ w .Header ().Set ("Content-Type" , "application/json" )
239+ json .NewEncoder (w ).Encode (mediaFiles )
240+ }
241+
242+ func handleProcessMedia (w http.ResponseWriter , r * http.Request ) {
243+ var request struct {
244+ File string `json:"file"`
245+ NewName string `json:"newName"`
246+ }
247+
248+ err := json .NewDecoder (r .Body ).Decode (& request )
249+ if err != nil {
250+ http .Error (w , "Invalid request" , http .StatusBadRequest )
251+ return
252+ }
253+
254+ sourceFile := filepath .Join (config .Server .MediaFolder , request .File )
255+ ext := filepath .Ext (request .File )
256+ newFileName := request .NewName + ext
257+ destFile := filepath .Join (config .Server .AssetFolder , newFileName )
258+
259+ // Open the source image
260+ src , err := imaging .Open (sourceFile )
261+ if err != nil {
262+ http .Error (w , "Error opening source image" , http .StatusInternalServerError )
263+ return
264+ }
265+
266+ // Resize the image
267+ var resized image.Image
268+ if config .Server .ImageResize .Method == "fit" {
269+ resized = imaging .Fit (src , config .Server .ImageResize .MaxWidth , 0 , imaging .Lanczos )
270+ } else {
271+ resized = imaging .Fill (src , config .Server .ImageResize .MaxWidth , 0 , imaging .Center , imaging .Lanczos )
272+ }
273+
274+ // Save the resized image
275+ err = imaging .Save (resized , destFile )
276+ if err != nil {
277+ http .Error (w , "Error saving resized image" , http .StatusInternalServerError )
278+ return
279+ }
280+
281+ // Create and save thumbnail
282+ var thumbnail image.Image
283+ if config .Server .ThumbnailResize .Method == "fit" {
284+ thumbnail = imaging .Fit (src , config .Server .ThumbnailResize .MaxWidth , 0 , imaging .Lanczos )
285+ } else {
286+ thumbnail = imaging .Fill (src , config .Server .ThumbnailResize .MaxWidth , 0 , imaging .Center , imaging .Lanczos )
287+ }
288+
289+ thumbnailFile := filepath .Join (config .Server .AssetFolder , "thumb_" + newFileName )
290+ err = imaging .Save (thumbnail , thumbnailFile )
291+ if err != nil {
292+ http .Error (w , "Error saving thumbnail" , http .StatusInternalServerError )
293+ return
294+ }
295+
296+ response := struct {
297+ Filename string `json:"filename"`
298+ }{
299+ Filename : newFileName ,
300+ }
301+
302+ w .Header ().Set ("Content-Type" , "application/json" )
303+ json .NewEncoder (w ).Encode (response )
304+ }
0 commit comments