summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkali kaneko (leap communications) <kali@leap.se>2021-11-15 21:35:53 +0100
committerkali kaneko (leap communications) <kali@leap.se>2021-11-15 21:47:46 +0100
commit82364eb76a56e1216bf3357e1287742205d5553c (patch)
tree908f5d92237d6756a10637a4b7813084628fadd9
parentadc296c2d513239444d0a6c1725e89720c2c715c (diff)
naive motd json format implementation
-rw-r--r--branding/motd-cli/.gitignore1
-rw-r--r--branding/motd-cli/README.md57
-rw-r--r--branding/motd-cli/main.go120
-rw-r--r--branding/motd-cli/motd-example.json14
4 files changed, 192 insertions, 0 deletions
diff --git a/branding/motd-cli/.gitignore b/branding/motd-cli/.gitignore
new file mode 100644
index 0000000..e26717e
--- /dev/null
+++ b/branding/motd-cli/.gitignore
@@ -0,0 +1 @@
+motd-cli
diff --git a/branding/motd-cli/README.md b/branding/motd-cli/README.md
new file mode 100644
index 0000000..cfe8a38
--- /dev/null
+++ b/branding/motd-cli/README.md
@@ -0,0 +1,57 @@
+MOTD (message of the day)
+=========================
+
+This is a stub until a more sophisticated motd mechanism can be implemented in
+the future, with better platform integration.
+
+Providers can opt-in to the motd feature (only riseup is using it at the moment).
+
+If motd is enabled for a given provider, the client will attempt to fetch
+the motd.json file from a well-known URL, and will display the first valid
+message on the splash screen.
+
+The structure of the `motd.json` file is like follows:
+
+```
+{
+ "motd": [{
+ "begin": "Jan 1 2021 00:00:00",
+ "end": "Dec 31 2021 23:59:00",
+ "type": "daily",
+ "platform": "all",
+ "text": [
+ { "lang": "en",
+ "str": "This is a <a href='https://leap.se'>test!</a>"},
+ { "lang": "es",
+ "str": "Esto es una <a href='https://leap.se'>pruebita!</a>"}
+ ]}
+ ]
+}
+```
+
+Valid values are:
+
+* Begin, End are date strings, like "Jan 1 2021 00:00:00".
+* Type: "once" for a one-shot message, "daily" for a message that is displayed daily during the specified duration.
+* Platform: one of "windows", "linux", "osx" or "all".
+
+The text message can contain links.
+
+You can use the `motd-cli` tool to parse and validate the json:
+
+```
+❯ ./motd-cli
+file: motd-example.json
+count: 1
+
+Message 1 ✓
+-----------
+Type: daily ✓
+Platform: all ✓
+Languages: 2 ✓
+```
+
+Notes: I'm considering adding an explicit layer of verification of the motd
+payload. Please comment on
+[#554](https://0xacab.org/leap/bitmask-vpn/-/issues/554) if you have an opinion
+on this.
diff --git a/branding/motd-cli/main.go b/branding/motd-cli/main.go
new file mode 100644
index 0000000..6cfd29e
--- /dev/null
+++ b/branding/motd-cli/main.go
@@ -0,0 +1,120 @@
+package main
+
+import (
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+)
+
+const defaultFile = "motd-example.json"
+
+const OK = "✓"
+const WRONG = "☓"
+
+/* TODO move structs to pkg/config/motd module, import from there */
+
+type Messages struct {
+ Messages []Message `json:"motd"`
+}
+
+func (m *Messages) Length() int {
+ return len(m.Messages)
+}
+
+type Message struct {
+ Begin string `json:"begin"`
+ End string `json:"end"`
+ Type string `json:"type"`
+ Platform string `json:"platform"`
+ Text []LocalizedText `json:"text"`
+}
+
+func (m *Message) IsValid() bool {
+ valid := (m.IsValidBegin() && m.IsValidEnd() &&
+ m.IsValidType() && m.IsValidPlatform() && m.HasLocalizedText())
+ return valid
+}
+
+func (m *Message) IsValidBegin() bool {
+ return true
+}
+
+func (m *Message) IsValidEnd() bool {
+ return true
+}
+
+func (m *Message) IsValidType() bool {
+ switch m.Type {
+ case "once", "daily":
+ return true
+ default:
+ return false
+ }
+}
+
+func (m *Message) IsValidPlatform() bool {
+ switch m.Platform {
+ case "windows", "linux", "osx", "all":
+ return true
+ default:
+ return false
+ }
+}
+
+func (m *Message) HasLocalizedText() bool {
+ return true
+}
+
+type LocalizedText struct {
+ Lang string `json:"lang"`
+ Str string `json:"str"`
+}
+
+func main() {
+ // TODO pass url flag too, to fetch and validate remote file
+ file := flag.String("file", "", "file to validate")
+ flag.Parse()
+ f := *file
+ if f == "" {
+ f = defaultFile
+ }
+
+ fmt.Println("file:", f)
+ m := parseFile(f)
+ fmt.Printf("count: %v\n", m.Length())
+ fmt.Println()
+ for i, msg := range m.Messages {
+ fmt.Printf("Message %d %v\n-----------\n", i+1, mark(msg.IsValid()))
+ fmt.Printf("Type: %s %v\n", msg.Type, mark(msg.IsValidType()))
+ fmt.Printf("Platform: %s %v\n", msg.Platform, mark(msg.IsValidPlatform()))
+ fmt.Printf("Languages: %d %v\n", len(msg.Text), mark(msg.HasLocalizedText()))
+ if !msg.IsValid() {
+ os.Exit(1)
+ }
+ }
+}
+
+func parseFile(f string) Messages {
+ jsonFile, err := os.Open(f)
+ if err != nil {
+ panic(err)
+ }
+ defer jsonFile.Close()
+ byteVal, err := ioutil.ReadAll(jsonFile)
+ if err != nil {
+ panic(err)
+ }
+ var m Messages
+ json.Unmarshal(byteVal, &m)
+ return m
+}
+
+func mark(val bool) string {
+ if val {
+ return OK
+ } else {
+ return WRONG
+ }
+}
diff --git a/branding/motd-cli/motd-example.json b/branding/motd-cli/motd-example.json
new file mode 100644
index 0000000..47bf635
--- /dev/null
+++ b/branding/motd-cli/motd-example.json
@@ -0,0 +1,14 @@
+{
+ "motd": [{
+ "begin": "Jan 1 2021 00:00:00",
+ "end": "Dec 31 2021 23:59:00",
+ "type": "daily",
+ "platform": "all",
+ "text": [
+ { "lang": "en",
+ "str": "This is a <a href='https://leap.se'>test!</a>"},
+ { "lang": "es",
+ "str": "Esto es una <a href='https://leap.se'>pruebita!</a>"}
+ ]}
+ ]
+}