Compare commits

..

37 commits
v5.0.0 ... main

Author SHA1 Message Date
351dc04764 Merge pull request 'chores: bump couleuvre -> v0.13.0' (#32) from vlbeaudoin/chores/bump-couleuvre into main
Reviewed-on: #32
2025-03-27 18:24:28 -04:00
b5589c2fee chores: bump couleuvre -> v0.13.0
Ajuster code pour considérer upgrade de dependency

Fix ordre de [App.Parse] et [App.AddCommands] dans cmd/

Exécuter `go get -u` pour mettre à jour les autres modules
2025-03-27 18:19:00 -04:00
cdd6083dc6 Merge pull request 'fix: dockerfile ne copie pas les go source files de la racine' (#31) from vlbeaudoin/fix/dockerfile-v8 into main
Reviewed-on: #31
2025-03-27 17:52:51 -04:00
b4669a9551 fix: dockerfile ne copie pas les go source files de la racine
Ajouter *.go à build step copy

Ajouter LICENSE à build step copy

Retirer pkg/ de build step add

Retirer apk upgrade de run step - plus prévisible si on utilise direct
ce que les image distributors ont packagés
2025-03-27 17:46:24 -04:00
c091aad796 Merge pull request 'refactor!: renommer module et réorganiser fichiers' (#30) from vlbeaudoin/major/v8 into main
Reviewed-on: #30
2025-03-27 17:35:18 -04:00
217b17d436 refactor!: renommer module et réorganiser fichiers
BREAKING: Rapporter fichiers `pkg/*.go` à la racine
BREAKING: Bump version du module à `git.agecem.com/agecem/babillard/v8` et ajuster
les références
2025-03-27 17:32:04 -04:00
0d8f880023 Merge pull request 'feature(ui): Reload contenu après dernière image' (#29) from vlbeaudoin/feature/auto-reload-contenu into main
Reviewed-on: #29
2025-02-17 18:13:14 -05:00
bfddebed0e feature(ui): Reload contenu après dernière image 2025-02-17 18:10:56 -05:00
da267669eb Merge pull request 'fix(ui): Éviter un écran noir comme première image' (#28) from vlbeaudoin/fix/ui-ecran-noir into main
Reviewed-on: #28
2025-02-17 17:58:53 -05:00
0f3660cb91 fix(ui): Éviter un écran noir comme première image
executionLoop() exécuté une fois avant que l'interval commence pour
éviter de rester sur un écran noir
2025-02-17 17:56:58 -05:00
21bf53de43 Merge pull request 'chores: Uniformiser case pour statements dans Dockerfile' (#27) from vlbeaudoin/chores/fix-capitalization-Dockerfile into main
Reviewed-on: #27
2025-02-17 17:56:06 -05:00
b7c4b1a4be chores: Uniformiser case pour statements dans Dockerfile 2025-02-17 17:54:15 -05:00
ebe7ba7445 Merge pull request 'ui: rajouter jquery et slider, comment out carousel' (#26) from vlbeaudoin/feature/api-v2-et-cleanups into main
Reviewed-on: #26
2025-02-12 17:42:06 -05:00
5a21a5154b ui: rajouter jquery et slider, comment out carousel 2025-02-12 17:18:18 -05:00
52dd5693fb wip: APIv2, UI rework, js cleanup
Retirer jquery

etc.
2025-02-11 21:24:42 -05:00
37031749b4 Merge pull request 'kubernetes: toujours pull image latest' (#25) from vlbeaudoin/kubernetes/image-pull-always into main
Reviewed-on: #25
2025-02-10 18:18:53 -05:00
bd455da46a kubernetes: toujours pull image latest 2025-02-10 18:17:50 -05:00
6421d1c617 Merge pull request 'feature(ui): randomize timer slider' (#24) from vlbeaudoin/feature/slider-random-timer into main
Reviewed-on: #24
2025-02-10 17:54:40 -05:00
f07deec71a feature(ui): randomize timer slider
10 secs -> rand(15000,20000)
2025-02-10 17:50:27 -05:00
f75dff011a Merge pull request 'kubernetes: remettre tag :latest à image d'app de babillard' (#22) from vlbeaudoin/kubernetes/latest-image into main
Reviewed-on: #22
2025-02-04 19:14:15 -05:00
87ea8e6068 kubernetes: remettre tag :latest à image d'app de babillard 2025-02-04 19:13:03 -05:00
6fbd412ecc Merge pull request 'kubernetes: bump babillard à 7.0.3 et monter contenu par nfs' (#21) from kubernetes/nfs-volume into main
Reviewed-on: #21
2025-02-04 19:07:34 -05:00
97c5bf5791 kubernetes: bump babillard à 7.0.3 et WIP nfs volume 2025-02-04 18:14:46 -05:00
1012810927 Merge pull request 'kubernetes: ajouter deployment.yaml et service.yaml' (#20) from vlbeaudoin/deployment/kubernetes into main
Reviewed-on: #20
2025-02-04 17:34:39 -05:00
61046f4690 kubernetes: ajouter deployment.yaml et service.yaml
NodePort 30001
2025-02-04 17:33:02 -05:00
ae5fc2f996 Merge pull request 'fix(compose): Utiliser babillard.yaml au lieu de .babillard.yaml' (#19) from vlbeaudoin/fix/compose-babillard-config into main
Reviewed-on: #19
2025-01-31 18:01:12 -05:00
b265d7ad81 fix(compose): Utiliser babillard.yaml au lieu de .babillard.yaml
Pour config utilisée par docker-compose
2025-01-31 17:59:44 -05:00
951ed87641 Merge pull request 'fix(Dockerfile): répertoire à go build' (#18) from vlbeaudoin/fix/dockerfile-go-build into main
Reviewed-on: #18
2025-01-31 17:07:17 -05:00
45df362fc5 fix(Dockerfile): répertoire à go build 2025-01-31 17:06:15 -05:00
15a32f4d5e Merge pull request 'major v7: Standardiser l'organisation du projet' (#17) from vlbeaudoin/major/v7 into main
Reviewed-on: #17
2025-01-31 16:38:27 -05:00
6cdc40926b major v7: Standardiser l'organisation du projet 2025-01-31 16:37:16 -05:00
7c4e8d8227 Merge pull request 'BREAKING: Déplacer config à cmd.app.Config et bump couleuvre' (#14) from refactor/app-config into main
Reviewed-on: #14
2023-12-04 21:32:38 -05:00
3b965105fa docs: add examples/babillard.yaml 2023-12-04 21:31:01 -05:00
72ff53f846 change!: move config to cmd.app.Config
bump: couleuvre -> `v0.10.0`

Move `couleuvre.NewApp` to `cmd.init`

Make flags target `&cmd.app.Config`

Fix `ServerCmdExecuter`'s `RunServer` parameters

Fix call to `app.Parse` in `cmd.Execute`

BREAKING: Remove `cmd.Cfg()`
BREAKING: Remove `cmd.cfg config.Config`
2023-12-04 21:27:51 -05:00
a3c2c8d1f0 change!: remove config.Config dependency injection in ContenuHandler
`ContenuHandler` now only stores a `ContenuDir string` instead of a
whole config.

BREAKING: change `handlers.RunServer` parameters to `contenuDir string, serverPort int`
2023-12-04 21:23:25 -05:00
c0f976e7cf Merge pull request 'Fix problèmes docker depuis couleuvre' (#13) from fix/docker into main
Reviewed-on: #13
2023-12-04 19:21:30 -05:00
4e054f988b fix: problèmes docker depuis couleuvre
Ajouter `config/` à `build` step

Réorganiser ordre de flags et commande dans `services.server.command`
2023-12-04 19:19:19 -05:00
27 changed files with 408 additions and 424 deletions

View file

@ -1,34 +1,27 @@
FROM golang:1.21.4 as build from golang:1.23 as build
LABEL author="Victor Lacasse-Beaudoin <vlbeaudoin@agecem.org>" label author="Victor Lacasse-Beaudoin <vlbeaudoin@agecem.org>"
LABEL license="MIT" label license="MIT"
LABEL licensee="AGECEM" label licensee="AGECEM"
LABEL repo="https://git.agecem.com/agecem/babillard" label repo="https://git.agecem.com/agecem/babillard"
WORKDIR /go/src/app workdir /go/src/app
COPY go.mod go.sum main.go ./ copy go.mod go.sum LICENSE cmd.go config.go contenu.go data.go handlers.go response.go ./
ADD cmd/ cmd/ add cmd/ cmd/
add ui/ ui/
ADD data/ data/ run CGO_ENABLED=0 go build -a ./cmd/babillard/
ADD handlers/ handlers/
ADD public/ public/
RUN CGO_ENABLED=0 go build -a -o babillard .
# Alpine # Alpine
FROM alpine:3.18.4 from alpine:3.21
RUN apk update && apk upgrade --no-cache workdir /app
WORKDIR /app add contenu/ contenu/
ADD contenu/ contenu/ copy --from=build /go/src/app/babillard /usr/bin/babillard
COPY --from=build /go/src/app/babillard /usr/bin/babillard cmd ["babillard", "server"]
CMD ["babillard", "server"]

20
Makefile Normal file
View file

@ -0,0 +1,20 @@
## This Makefile uses the help target explained in the following blogpost:
##
## https://victoria.dev/blog/how-to-create-a-self-documenting-makefile/
.DEFAULT_GOAL := help
.PHONY: help
help: ## Show this help
@egrep -h '\s##\s' $(MAKEFILE_LIST) | \
sort | \
awk \
'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
.PHONY: install
install: ## Use `go install` to build and link the executable
go install -a ./cmd/babillard/
.PHONY: build
build: ## Use `docker build` to build the container image
docker build . -f Dockerfile -t git.agecem.com/agecem/babillard:latest

View file

@ -2,6 +2,8 @@
Application web pour 'digital signage'. Application web pour 'digital signage'.
**CE DOCUMENT N'EST PLUS À JOUR**
Backend: Go avec `labstack/echo/v4` Backend: Go avec `labstack/echo/v4`
Frontend: html, css, jquery Frontend: html, css, jquery

56
cmd.go Normal file
View file

@ -0,0 +1,56 @@
package babillard
import (
"flag"
"codeberg.org/vlbeaudoin/couleuvre"
)
var app couleuvre.App[Config]
func init() {
app = couleuvre.App[Config]{EnvPrefix: "babillard"}
flag.StringVar(&app.Config.ServerContenuDir, ServerContenuDirName, ServerContenuDirDefault, ServerContenuDirDescription)
flag.IntVar(&app.Config.ServerPort, ServerPortName, ServerPortDefault, ServerPortDescription)
}
const (
ServerContenuDirName = "servercontenudir"
ServerContenuDirDefault = "contenu"
ServerContenuDirDescription = "Répertoire du contenu à exposer"
ServerPortName = "serverport"
ServerPortDefault int = 8080
ServerPortDescription = "Port réseau à utiliser pour le serveur"
)
const (
ServerCmdName = "server"
ServerCmdDesc = "Démarrer le serveur web"
)
func ServerCmdExecuter(args ...string) error {
RunServer(app.Config)
return nil
}
func Execute() error {
if err := app.AddCommands(couleuvre.Command{
Name: ServerCmdName,
Description: ServerCmdDesc,
Executer: couleuvre.ExecuterFunc(ServerCmdExecuter),
}); err != nil {
return err
}
if err := app.Parse(); err != nil {
return err
}
if err := app.Execute(flag.Args()...); err != nil {
return err
}
return nil
}

View file

@ -1,5 +1,5 @@
/* /*
Copyright © 2021 AGECEM Copyright © 2021-2025 AGECEM
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -24,11 +24,11 @@ package main
import ( import (
"log" "log"
"git.agecem.com/agecem/babillard/cmd" "git.agecem.com/agecem/babillard/v8"
) )
func main() { func main() {
if err := cmd.Execute(); err != nil { if err := babillard.Execute(); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

View file

@ -1,67 +0,0 @@
package cmd
import (
"flag"
"os"
"codeberg.org/vlbeaudoin/couleuvre"
"git.agecem.com/agecem/babillard/config"
"git.agecem.com/agecem/babillard/handlers"
)
var cfg config.Config
func Cfg() config.Config { return cfg }
func init() {
flag.StringVar(&cfg.ServerContenuDir, ServerContenuDirName, ServerContenuDirDefault, ServerContenuDirDescription)
flag.IntVar(&cfg.ServerPort, ServerPortName, ServerPortDefault, ServerPortDescription)
}
const (
ServerContenuDirName = "servercontenudir"
ServerContenuDirDefault = "contenu"
ServerContenuDirDescription = "Répertoire du contenu à exposer"
ServerPortName = "serverport"
ServerPortDefault int = 8080
ServerPortDescription = "Port réseau à utiliser pour le serveur"
)
const (
ServerCmdName = "server"
ServerCmdDesc = "Démarrer le serveur web"
)
func ServerCmdExecuter() error {
handlers.RunServer(Cfg())
return nil
}
func Execute() error {
app := couleuvre.NewApp("BABILLARD_", ".", "_")
if err := app.Parse(&cfg); err != nil {
return err
}
if err := app.NewCommand(ServerCmdName, ServerCmdDesc, ServerCmdExecuter); err != nil {
return err
}
var commandName string
if len(os.Args) > 1 {
commandName = flag.Arg(0)
}
cmd, err := app.ParseCommand(commandName)
if err != nil {
return err
}
if err := cmd.Execute(); err != nil {
return err
}
return nil
}

View file

@ -8,7 +8,7 @@ services:
volumes: volumes:
- 'config:/app/config' - 'config:/app/config'
- 'contenu:/app/contenu' - 'contenu:/app/contenu'
command: ['babillard', 'server', '--config', '/app/config/.babillard.yaml'] command: ['babillard', '--config', '/app/config/babillard.yaml', 'server']
volumes: volumes:
config: config:

View file

@ -1,4 +1,4 @@
package config package babillard
type Config struct { type Config struct {
ServerContenuDir string ServerContenuDir string

68
contenu.go Normal file
View file

@ -0,0 +1,68 @@
package babillard
import (
"fmt"
"log"
"net/http"
"strings"
"github.com/labstack/echo/v4"
)
// pre-v2
type ContenuHandler struct {
ContenuDir string
}
func NewContenuHandler(contenuDir string) (h ContenuHandler) {
h.ContenuDir = contenuDir
return
}
func (h ContenuHandler) HandleAPIContenuList(c echo.Context) error {
contenu_dir := h.ContenuDir
files, err := ListContenu(contenu_dir)
if err != nil {
log.Println(err)
return c.JSON(http.StatusInternalServerError, map[string]string{
"message": "Internal Server Error",
"error": err.Error(),
})
}
return c.String(http.StatusOK, strings.Join(files, ";"))
}
func (h ContenuHandler) HandleAPIContenuFile(c echo.Context) error {
filename := c.Param("filename")
contenu_dir := h.ContenuDir
if filename == ".gitkeep" {
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not Found"})
}
return c.File(fmt.Sprintf("%s/%s", contenu_dir, filename))
}
// v2
func APIv2ListContenu(cfg Config) echo.HandlerFunc {
return func(c echo.Context) error {
files, err := ListContenu(cfg.ServerContenuDir)
if err != nil {
return c.JSON(http.StatusInternalServerError, ErrorResponse{Error: err.Error()})
}
return c.JSON(http.StatusOK, NewContenuResponse(files))
}
}
// ui
func UIContenuFichier(cfg Config) echo.HandlerFunc {
return func(c echo.Context) error {
return c.File(fmt.Sprintf("%s/%s", cfg.ServerContenuDir, c.Param("fichier")))
}
}

42
data.go Normal file
View file

@ -0,0 +1,42 @@
package babillard
import (
"fmt"
"os"
)
var forbiddenFiles = []string{".gitkeep", "messages.txt", "Thumbs.db"}
func ListContenu(path string) (files []string, err error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
stats, err := file.Stat()
if err != nil {
return nil, err
}
if !stats.IsDir() {
return nil, fmt.Errorf("contenu '%s' n'est pas un répertoire", path)
}
fileInfos, err := file.Readdir(-1)
if err != nil {
return nil, err
}
fileLoop:
for _, fileInfo := range fileInfos {
for _, forbiddenFile := range forbiddenFiles {
if fileInfo.Name() == forbiddenFile {
continue fileLoop
}
}
files = append(files, fileInfo.Name())
}
return files, nil
}

View file

@ -1,24 +0,0 @@
package data
import "os"
func ListContenu(path string) ([]string, error) {
var files []string
f, err_open := os.Open(path)
defer f.Close()
if err_open != nil {
return nil, err_open
}
fileInfo, err_read := f.Readdir(-1)
if err_read != nil {
return nil, err_read
}
for _, file := range fileInfo {
if file.Name() != ".gitkeep" && file.Name() != "messages.txt" {
files = append(files, file.Name())
}
}
return files, nil
}

2
examples/babillard.yaml Normal file
View file

@ -0,0 +1,2 @@
serverport: 9999
servercontenudir: '/dev/null'

30
go.mod
View file

@ -1,30 +1,26 @@
module git.agecem.com/agecem/babillard module git.agecem.com/agecem/babillard/v8
go 1.21.3 go 1.23.0
toolchain go1.21.4 toolchain go1.23.6
require ( require (
codeberg.org/vlbeaudoin/couleuvre v0.8.0 codeberg.org/vlbeaudoin/couleuvre v0.13.0
github.com/labstack/echo/v4 v4.11.3 github.com/labstack/echo/v4 v4.13.3
) )
require ( require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/goccy/go-yaml v1.16.0 // indirect
github.com/kr/text v0.2.0 // indirect github.com/labstack/gommon v0.4.2 // indirect
github.com/labstack/gommon v0.4.1 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.16.0 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/net v0.19.0 // indirect golang.org/x/net v0.38.0 // indirect
golang.org/x/sys v0.15.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.23.0 // indirect
golang.org/x/time v0.5.0 // indirect golang.org/x/time v0.11.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
) )

58
go.sum
View file

@ -1,49 +1,35 @@
codeberg.org/vlbeaudoin/couleuvre v0.8.0 h1:61lJ8zICGWiBX2Ao0+p1L+fU78KKibgJ5M6kCFHXjN0= codeberg.org/vlbeaudoin/couleuvre v0.13.0 h1:N2gAzpItFthQ0aPzMQjntRsrqrEXwuo0u6VHSGA/V6o=
codeberg.org/vlbeaudoin/couleuvre v0.8.0/go.mod h1:+M8nPA/3LknsY72RP0ZHCZycQ1SPxxRoXpnyHeSNE7U= codeberg.org/vlbeaudoin/couleuvre v0.13.0/go.mod h1:0RvzStph7J4/M+mZb903hn4GSYrTBjXYVJv72Pwpa90=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/goccy/go-yaml v1.16.0 h1:d7m1G7A0t+logajVtklHfDYJs2Et9g3gHwdBNNFou0w=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/goccy/go-yaml v1.16.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/labstack/echo/v4 v4.11.3 h1:Upyu3olaqSHkCjs1EJJwQ3WId8b8b1hxbogyommKktM= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/labstack/gommon v0.4.1 h1:gqEff0p/hTENGMABzezPoPSRtIh1Cvw0ueMOe0/dfOk=
github.com/labstack/gommon v0.4.1/go.mod h1:TyTrpPqxR5KMk8LKVtLmfMjeQ5FEkBYdxLYPw/WfrOM=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -1,12 +1,11 @@
package handlers package babillard
import ( import (
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"git.agecem.com/agecem/babillard/config" "git.agecem.com/agecem/babillard/v8/ui"
"git.agecem.com/agecem/babillard/public"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware" "github.com/labstack/echo/v4/middleware"
) )
@ -19,12 +18,16 @@ API Specifications
'/api' | GET | Affiche les spécifications API '/api' | GET | Affiche les spécifications API
'/api/contenu' | GET | Affiche le nom des fichiers dans 'contenu/' '/api/contenu' | GET | Affiche le nom des fichiers dans 'contenu/'
'/api/contenu/{filename}' | GET | Affiche le fichier 'contenu/{filename}' '/api/contenu/{filename}' | GET | Affiche le fichier 'contenu/{filename}'
-----` -----
v2
--
'/api/v2/contenu' | GET | Affiche les noms des fichiers dans 'contenu/'
`
return c.String(http.StatusOK, apispec) return c.String(http.StatusOK, apispec)
} }
func RunServer(cfg config.Config) { func RunServer(cfg Config) {
log.Print("[I] Starting webserver") log.Print("[I] Starting webserver")
e := echo.New() e := echo.New()
@ -33,24 +36,30 @@ func RunServer(cfg config.Config) {
e.Group("").Use(middleware.StaticWithConfig(middleware.StaticConfig{ e.Group("").Use(middleware.StaticWithConfig(middleware.StaticConfig{
Root: "/html/", Root: "/html/",
Filesystem: http.FS(public.HTMLFS()), Filesystem: http.FS(ui.HTMLFS()),
})) }))
e.Group("/public/css").Use(middleware.StaticWithConfig(middleware.StaticConfig{ e.Group("/public/css").Use(middleware.StaticWithConfig(middleware.StaticConfig{
Root: "/css/", Root: "/css/",
Filesystem: http.FS(public.CSSFS()), Filesystem: http.FS(ui.CSSFS()),
})) }))
e.Group("/public/js").Use(middleware.StaticWithConfig(middleware.StaticConfig{ e.Group("/public/js").Use(middleware.StaticWithConfig(middleware.StaticConfig{
Root: "/js/", Root: "/js/",
Filesystem: http.FS(public.JSFS()), Filesystem: http.FS(ui.JSFS()),
})) }))
groupAPI := e.Group("/api") groupAPI := e.Group("/api")
contenuHandler := NewContenuHandler(cfg) contenuHandler := NewContenuHandler(cfg.ServerContenuDir)
groupAPI.GET("/", HandleAPIShow) groupAPI.GET("/", HandleAPIShow)
groupAPI.GET("/contenu/", contenuHandler.HandleAPIContenuList) groupAPI.GET("/contenu/", contenuHandler.HandleAPIContenuList)
groupAPI.GET("/contenu/:filename/", contenuHandler.HandleAPIContenuFile) groupAPI.GET("/contenu/:filename/", contenuHandler.HandleAPIContenuFile)
groupAPI.GET("/v2/contenu/", APIv2ListContenu(cfg))
groupUI := e.Group("/ui")
groupUI.GET("/contenu/:fichier/", UIContenuFichier(cfg))
e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", cfg.ServerPort))) e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", cfg.ServerPort)))
} }

View file

@ -1,47 +0,0 @@
package handlers
import (
"fmt"
"log"
"net/http"
"strings"
"git.agecem.com/agecem/babillard/config"
"git.agecem.com/agecem/babillard/data"
"github.com/labstack/echo/v4"
)
type ContenuHandler struct {
Cfg config.Config
}
func NewContenuHandler(cfg config.Config) (h ContenuHandler) {
h.Cfg = cfg
return
}
func (h ContenuHandler) HandleAPIContenuList(c echo.Context) error {
contenu_dir := h.Cfg.ServerContenuDir
files, err := data.ListContenu(contenu_dir)
if err != nil {
log.Println(err)
return c.JSON(http.StatusInternalServerError, map[string]string{
"message": "Internal Server Error",
"error": err.Error(),
})
}
return c.String(http.StatusOK, strings.Join(files, ";"))
}
func (h ContenuHandler) HandleAPIContenuFile(c echo.Context) error {
filename := c.Param("filename")
contenu_dir := h.Cfg.ServerContenuDir
if filename == ".gitkeep" {
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not Found"})
}
return c.File(fmt.Sprintf("%s/%s", contenu_dir, filename))
}

31
k8s/deployment.yaml Normal file
View file

@ -0,0 +1,31 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: babillard-deployment
labels:
app: babillard
spec:
replicas: 1
selector:
matchLabels:
app: babillard
template:
metadata:
labels:
app: babillard
spec:
containers:
- name: babillard
image: git.agecem.com/agecem/babillard:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
volumeMounts:
- name: babillard-nfs
mountPath: "/app/contenu"
volumes:
- name: babillard-nfs
nfs:
server: fs.agecem.com
path: /mnt/Pool1/babillard
readOnly: true

13
k8s/service.yaml Normal file
View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: babillard-service
spec:
type: NodePort
selector:
app: babillard
ports:
- protocol: TCP
port: 8080
targetPort: 8080
nodePort: 30001

View file

@ -1,79 +0,0 @@
body {
margin: 0;
padding: 0;
border: 0;
display: flex;
flex-flow: column;
height: 100vh;
}
embed {
max-width: 100%;
height: 100%;
object-fit: contain;
}
#contenu {
background-color: black;
text-align: center;
width: 100%;
flex: 1;
min-height: 0;
}
#bar {
width: 100%;
background-image: linear-gradient(to right, #033ead, #3093d1);
color: white;
font-family: 'Roboto', sans-serif;
font-weight: bold;
display: flex;
align-items: center;
min-height: 75px;
}
img#bar-bg {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
}
#time {
font-size: 300%;
height: 53px;
}
#text-content {
white-space: nowrap;
z-index: 1;
display: block;
height: 100%;
padding-top: 55px;
position: relative;
}
#text-container {
height: 100%;
background-image: linear-gradient(to right, #033ead, #3093d1);
display: flex;
align-items: center;
font-size: 20px;
flex-grow: 1;
}
#text-content div {
display: block;
position: fixed;
height: 100%;
}
#date-time {
display: flex;
flex-flow: column;
align-items: center;
height: 100%;
background-color: #033ead;
z-index: 1;
width: 225px;
}

View file

@ -1,43 +0,0 @@
<html>
<head>
<title>AGECEM | slider</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="/public/js/slider.js"></script>
<!-- BROKEN, brise slider.js quand inclu
<script src="text.js"></script>
!-->
<link rel="stylesheet" href="/public/css/style.css">
</head>
<body>
<p id="debug"></p>
<div id="contenu">
<embed id="image"/>
</div>
<!-- BROKEN
<div id="bar">
<div id="date-time">
<div id="time"></div>
<div id="date"></div>
</div>
<div id="text-container">
<div id="text-content">
<div>Ce texte sera remplacé par jQuery!</div>
</div>
</div>
</div>
--!>
</body>
</html>

View file

@ -1,65 +0,0 @@
// VARS
// Vitesses
var vitesseTexte = 4000; // En millisecondes
// Coordonnées
var pointInitial = '100%';
var pointDestination = '-=2000px';
// Messages
var messageDiv = '#text-content div'
var messages = [];
var indexMessages = 0;
var fontSize;
var fontSizeLength;
// FUNCS
function animerTexte(){
// Diriger le texte vers la droite jusqu'à `pointDestination'.
// Récursivement reset la position du texte.
$(messageDiv).animate({left: pointDestination}, vitesseTexte, 'linear', resetTexte);
}
function resetTexte(){
// Remettre le texte au point initial
$(messageDiv).css('left', pointInitial);
// Récursivement animer le texte
animerTexte();
}
function updateTexte(){
var message = messages[indexMessages];
$(messageDiv).text(message);
augmenterIndex();
}
function augmenterIndex() {
if (indexMessages >= messages.length - 1) {
indexMessages = 0;
} else {
indexMessages ++;
}
}
function initialiserMessages(){
fontSize = $(messageDiv).css('fontSize');
fontSizeLength = fontSize.length;
// TODO Importer messages
messages = ['hello, world!'];
// TODO pointDestination = -1 * longueurMessage
//pointDestination = messages[0].width * fontSize.substring(fontSize.length-2);
pointDestination = messages[indexMessages].width;
}
// EXEC
$(function(){
//initialiserMessages();
resetTexte();
});

20
response.go Normal file
View file

@ -0,0 +1,20 @@
package babillard
type ErrorResponse struct {
Error string
}
type MessageResponse struct {
Message string
}
type ContenuResponse struct {
Data struct {
Contenu []string
}
}
func NewContenuResponse(fichiers []string) (response ContenuResponse) {
response.Data.Contenu = fichiers
return
}

22
ui/css/style.css Normal file
View file

@ -0,0 +1,22 @@
body {
margin: 0;
padding: 0;
border: 0;
display: flex;
flex-flow: column;
height: 100vh;
}
embed {
max-width: 100%;
height: 100%;
object-fit: contain;
}
#contenu {
background-color: black;
text-align: center;
width: 100%;
flex: 1;
min-height: 0;
}

View file

@ -1,18 +1,18 @@
package public package ui
import "embed" import "embed"
//go:embed html/* //go:embed html/*.html
var htmlFS embed.FS var htmlFS embed.FS
func HTMLFS() embed.FS { return htmlFS } func HTMLFS() embed.FS { return htmlFS }
//go:embed css/* //go:embed css/*.css
var cssFS embed.FS var cssFS embed.FS
func CSSFS() embed.FS { return cssFS } func CSSFS() embed.FS { return cssFS }
//go:embed js/* //go:embed js/*.js
var jsFS embed.FS var jsFS embed.FS
func JSFS() embed.FS { return jsFS } func JSFS() embed.FS { return jsFS }

17
ui/html/index.html Normal file
View file

@ -0,0 +1,17 @@
<html>
<head>
<title>AGECEM | babillard</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link rel="stylesheet" href="/public/css/style.css">
<!--<script src="/public/js/carousel.js"></script>--!>
<script src="/public/js/slider.js"></script>
</head>
<body>
<div id="contenu">
<embed id="image"/>
</div>
</body>
</html>

32
ui/js/carousel.js Normal file
View file

@ -0,0 +1,32 @@
// 2025-02 Victor Lacasse-Beaudoin, AGECEM
//
// Carousel d'images à afficher sur https://babillard.agecem.com/ ainsi que
// sur la télévision du Centre-Multi Services de l'AGECEM.
//
// WIP
async function getContenu() {
const url = "/api/v2/contenu/";
try {
const response = await fetch(url);
if (!response.ok) {
//TODO start interval then refresh page to try again
throw new Error(`Response status: ${response.status}`);
}
json = await response.json();
console.log("[i] got contenu");
console.log(json);
//startCarousel(json);
}
catch (error) {
console.error(error.message);
}
}
function run(){
console.log("[i] run");
getContenu();
}
run();

View file

@ -10,15 +10,14 @@ function afficherImage() {
} }
function augmenterIndex() { function augmenterIndex() {
if (indexImages >= images.length - 1) {
indexImages = 0;
} else {
indexImages ++; indexImages ++;
}
} }
function executionLoop(){ function executionLoop(){
//afficherIndex(); if (indexImages >= images.length) {
location.reload();
}
afficherImage(); afficherImage();
augmenterIndex(); augmenterIndex();
} }
@ -41,5 +40,6 @@ function obtenirContenu(){
$(function(){ $(function(){
obtenirContenu(); obtenirContenu();
var executionInterval = setInterval(executionLoop, 10000); executionLoop();
var executionInterval = setInterval(executionLoop, (Math.floor(Math.random() * 6)+15)*1000);
}); });