Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
version: "2"
run:
allow-parallel-runners: true
linters:
default: none
enable:
- dupl
- errcheck
- ginkgolinter
- goconst
- gocyclo
- govet
- ineffassign
- lll
- misspell
- nakedret
- prealloc
- revive
- staticcheck
- unconvert
- unparam
- unused
settings:
revive:
rules:
- name: comment-spacings
exclusions:
generated: lax
rules:
- linters:
- lll
path: api/*
- linters:
- dupl
- lll
path: internal/*
paths:
- third_party$
- builtin$
- examples$
formatters:
enable:
- gofmt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
2 changes: 1 addition & 1 deletion api/generate.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package api

//go:generate oapi-codegen --config=oapi-codegen.yaml epgstation-schema.json
//go:generate oapi-codegen --config=oapi-codegen.yaml epgstation-schema.json
2 changes: 1 addition & 1 deletion cmd/epgstationctl/main.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package main

import (
"github.com/miscord-dev/epgstationctl/internal/commands/root"
_ "github.com/miscord-dev/epgstationctl/internal/commands/channels"
_ "github.com/miscord-dev/epgstationctl/internal/commands/programs"
_ "github.com/miscord-dev/epgstationctl/internal/commands/recordings"
"github.com/miscord-dev/epgstationctl/internal/commands/root"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion internal/client/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ func parseJSONResponse(resp *http.Response, target interface{}) error {
}

return nil
}
}
14 changes: 7 additions & 7 deletions internal/client/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (c *EPGStationClient) GetChannels() (*epgstation.ChannelItems, error) {
if err != nil {
return nil, err
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
Expand All @@ -54,7 +54,7 @@ func (c *EPGStationClient) GetSchedules(params *epgstation.GetSchedulesParams) (
if err != nil {
return nil, err
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
Expand All @@ -73,7 +73,7 @@ func (c *EPGStationClient) GetBroadcastingPrograms(params *epgstation.GetSchedul
if err != nil {
return nil, err
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
Expand All @@ -92,7 +92,7 @@ func (c *EPGStationClient) GetRecordings(params *epgstation.GetRecordingParams)
if err != nil {
return nil, err
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
Expand All @@ -111,7 +111,7 @@ func (c *EPGStationClient) GetSchedulesChannelId(ctx interface{}, channelId epgs
if err != nil {
return nil, err
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
Expand All @@ -130,7 +130,7 @@ func (c *EPGStationClient) PostSchedulesSearch(ctx interface{}, body epgstation.
if err != nil {
return nil, err
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
Expand All @@ -142,4 +142,4 @@ func (c *EPGStationClient) PostSchedulesSearch(ctx interface{}, body epgstation.
}

return &programs, nil
}
}
2 changes: 1 addition & 1 deletion internal/commands/channels/channels.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,4 @@ func init() {
channelsCmd.AddCommand(listCmd)
channelsCmd.AddCommand(showCmd)
root.AddCommand(channelsCmd)
}
}
97 changes: 78 additions & 19 deletions internal/commands/programs/programs.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ import (
"github.com/spf13/cobra"
)

const (
outputFormatJSON = "json"
)

var (
channelID int
date string
days int
halfWidth bool
keyword string
limit int
channelID int
date string
days int
halfWidth bool
limit int
)

var programsCmd = &cobra.Command{
Expand Down Expand Up @@ -56,7 +59,7 @@ var listCmd = &cobra.Command{

// Add channel filter if provided
if channelID > 0 {
chID := epgstation.ChannelId(channelID)
chID := channelID
// Get specific channel schedule
channelParams := &epgstation.GetSchedulesChannelIdParams{
IsHalfWidth: halfWidth,
Expand All @@ -65,7 +68,7 @@ var listCmd = &cobra.Command{
channelParams.StartAt = params.StartAt
}
if days > 0 {
channelParams.Days = epgstation.Days(days)
channelParams.Days = days
}

schedules, err := client.GetSchedulesChannelId(nil, chID, channelParams)
Expand All @@ -75,13 +78,14 @@ var listCmd = &cobra.Command{

var formatter output.Formatter
switch cfg.Output.Format {
case "json":
case outputFormatJSON:
formatter = output.NewJSONFormatter(nil)
return formatter.Format(*schedules)
default:
formatter = output.NewTableFormatter(nil, cfg.Output.NoHeader)
// Custom formatting for Schedules - flatten to show programs with channel info
return formatSchedulesAsTable(*schedules, formatter)
}

return formatter.Format(*schedules)
}

schedules, err := client.GetSchedules(params)
Expand All @@ -91,13 +95,14 @@ var listCmd = &cobra.Command{

var formatter output.Formatter
switch cfg.Output.Format {
case "json":
case outputFormatJSON:
formatter = output.NewJSONFormatter(nil)
return formatter.Format(*schedules)
default:
formatter = output.NewTableFormatter(nil, cfg.Output.NoHeader)
// Custom formatting for Schedules - flatten to show programs with channel info
return formatSchedulesAsTable(*schedules, formatter)
}

return formatter.Format(*schedules)
},
}

Expand All @@ -123,13 +128,14 @@ var currentCmd = &cobra.Command{

var formatter output.Formatter
switch cfg.Output.Format {
case "json":
case outputFormatJSON:
formatter = output.NewJSONFormatter(nil)
return formatter.Format(*schedules)
default:
formatter = output.NewTableFormatter(nil, cfg.Output.NoHeader)
// Custom formatting for Schedules - flatten to show programs with channel info
return formatSchedulesAsTable(*schedules, formatter)
}

return formatter.Format(*schedules)
},
}

Expand Down Expand Up @@ -172,7 +178,7 @@ var searchCmd = &cobra.Command{

var formatter output.Formatter
switch cfg.Output.Format {
case "json":
case outputFormatJSON:
formatter = output.NewJSONFormatter(nil)
default:
formatter = output.NewTableFormatter(nil, cfg.Output.NoHeader)
Expand Down Expand Up @@ -200,4 +206,57 @@ func init() {
programsCmd.AddCommand(currentCmd)
programsCmd.AddCommand(searchCmd)
root.AddCommand(programsCmd)
}
}

// formatSchedulesAsTable formats schedule data in a user-friendly table format
func formatSchedulesAsTable(schedules epgstation.Schedules, formatter output.Formatter) error {
if len(schedules) == 0 {
fmt.Println("No programs found")
return nil
}

// Create a flat list of programs with channel information
type ProgramWithChannel struct {
ChannelName string
ChannelType string
ProgramName string
StartTime string
EndTime string
Description string
}

var programs []ProgramWithChannel
for _, schedule := range schedules {
channelName := schedule.Channel.Name

for _, program := range schedule.Programs {
startTime := formatUnixTime(int64(program.StartAt))
endTime := formatUnixTime(int64(program.EndAt))

description := ""
if program.Description != nil {
description = *program.Description
if len(description) > 50 {
description = description[:50] + "..."
}
}

programs = append(programs, ProgramWithChannel{
ChannelName: channelName,
ChannelType: string(schedule.Channel.ChannelType),
ProgramName: program.Name,
StartTime: startTime,
EndTime: endTime,
Description: description,
})
}
}

return formatter.Format(programs)
}

// formatUnixTime converts Unix timestamp (in milliseconds) to readable time
func formatUnixTime(unixTimeMS int64) string {
t := time.Unix(unixTimeMS/1000, 0)
return t.Format("15:04")
}
8 changes: 3 additions & 5 deletions internal/commands/recordings/recordings.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,11 @@ var listCmd = &cobra.Command{
}

if offset > 0 {
offsetParam := epgstation.Offset(offset)
params.Offset = &offsetParam
params.Offset = &offset
}

if limit > 0 {
limitParam := epgstation.Limit(limit)
params.Limit = &limitParam
params.Limit = &limit
}

recordings, err := client.GetRecordings(params)
Expand Down Expand Up @@ -117,4 +115,4 @@ func init() {
recordingsCmd.AddCommand(listCmd)
recordingsCmd.AddCommand(statusCmd)
root.AddCommand(recordingsCmd)
}
}
2 changes: 1 addition & 1 deletion internal/commands/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,4 @@ func GetConfig() *config.Config {

func AddCommand(cmd *cobra.Command) {
rootCmd.AddCommand(cmd)
}
}
2 changes: 1 addition & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ func NewConfig(serverURL string, timeout int, outputFormat string, noHeader bool

func (c *Config) GetAPIBaseURL() string {
return c.Server.URL + "/api"
}
}
19 changes: 15 additions & 4 deletions internal/output/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"io"
"os"
"reflect"


"github.com/olekukonko/tablewriter"
)
Expand Down Expand Up @@ -67,7 +66,7 @@ func (f *TableFormatter) Format(data interface{}) error {

func (f *TableFormatter) formatSlice(v reflect.Value) error {
if v.Len() == 0 {
fmt.Fprintln(f.writer, "No data found")
_, _ = fmt.Fprintln(f.writer, "No data found")
return nil
}

Expand Down Expand Up @@ -202,7 +201,19 @@ func (f *TableFormatter) formatValue(v reflect.Value) string {
return ""
}
return fmt.Sprintf("[%d items]", v.Len())
case reflect.Struct:
// For nested structs, show a summary instead of full structure
typeName := v.Type().Name()
if typeName == "" {
typeName = "struct"
}
return fmt.Sprintf("<%s>", typeName)
default:
return fmt.Sprintf("%v", v.Interface())
// Avoid showing memory addresses and internal representations
typeName := v.Type().Name()
if typeName != "" {
return fmt.Sprintf("<%s>", typeName)
}
return fmt.Sprintf("<%s>", v.Type().String())
}
}
}
Loading