|
@@ -35,33 +35,47 @@ func chattoClientFromEnv() (*chatto.Client, error) {
|
|
|
return chatto.NewClient(base, token), nil
|
|
return chatto.NewClient(base, token), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// formatGames renders games as a compact Chatto message body.
|
|
|
|
|
|
|
+// formatGames renders games as a Chatto Markdown message body.
|
|
|
func formatGames(games []game.Game, upcoming bool) string {
|
|
func formatGames(games []game.Game, upcoming bool) string {
|
|
|
if len(games) == 0 {
|
|
if len(games) == 0 {
|
|
|
if upcoming {
|
|
if upcoming {
|
|
|
- return "No upcoming free games announced."
|
|
|
|
|
|
|
+ return "🗓 **Upcoming free games:** none announced."
|
|
|
}
|
|
}
|
|
|
- return "No free games on offer right now."
|
|
|
|
|
|
|
+ return "🎮 **Current free games:** none on offer."
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
var b strings.Builder
|
|
var b strings.Builder
|
|
|
if upcoming {
|
|
if upcoming {
|
|
|
- b.WriteString("🗓 *Upcoming free games (Epic):*\n")
|
|
|
|
|
|
|
+ b.WriteString("## 🗓 Upcoming free games\n\n")
|
|
|
} else {
|
|
} else {
|
|
|
- b.WriteString("🎮 *Current free games:*\n")
|
|
|
|
|
|
|
+ b.WriteString("## 🎮 Current free games\n\n")
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // One table per store keeps columns uniform (dates only for epic).
|
|
|
|
|
+ b.WriteString("| Game | Store | Period | Link |\n")
|
|
|
|
|
+ b.WriteString("|---|---|---|---|\n")
|
|
|
for _, g := range games {
|
|
for _, g := range games {
|
|
|
- fmt.Fprintf(&b, "• [%s] %s", g.Store, g.Title)
|
|
|
|
|
- if !g.EndDate.IsZero() {
|
|
|
|
|
- if g.Kind == "upcoming" && !g.StartDate.IsZero() {
|
|
|
|
|
- fmt.Fprintf(&b, " — from %s", g.StartDate.Local().Format("02.01."))
|
|
|
|
|
- }
|
|
|
|
|
- fmt.Fprintf(&b, " (until %s)", g.EndDate.Local().Format("02.01."))
|
|
|
|
|
|
|
+ period := "—"
|
|
|
|
|
+ if g.Kind == "upcoming" && !g.StartDate.IsZero() && !g.EndDate.IsZero() {
|
|
|
|
|
+ period = fmt.Sprintf("from %s, until %s",
|
|
|
|
|
+ g.StartDate.Local().Format("02.01."),
|
|
|
|
|
+ g.EndDate.Local().Format("02.01."))
|
|
|
|
|
+ } else if !g.EndDate.IsZero() {
|
|
|
|
|
+ period = "until " + g.EndDate.Local().Format("02.01.")
|
|
|
}
|
|
}
|
|
|
- fmt.Fprintf(&b, "\n %s\n", g.URL)
|
|
|
|
|
|
|
+ fmt.Fprintf(&b, "| **%s** | %s | %s | [Store](%s) |\n",
|
|
|
|
|
+ escapePipe(g.Title), g.Store, period, g.URL)
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ b.WriteString("\n_As of now — free from/until 17:00 Europe/Berlin each._")
|
|
|
return b.String()
|
|
return b.String()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// escapePipe prevents table cell breakage via titles containing '|'.
|
|
|
|
|
+func escapePipe(s string) string {
|
|
|
|
|
+ return strings.ReplaceAll(s, "|", "\\|")
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// chattoSendCmd posts the current free games to a Chatto room.
|
|
// chattoSendCmd posts the current free games to a Chatto room.
|
|
|
func chattoSendCmd() *cobra.Command {
|
|
func chattoSendCmd() *cobra.Command {
|
|
|
var (
|
|
var (
|