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
62 changes: 61 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ A comprehensive command-line interface for [EPGStation](https://github.com/l3tnu
- **Recording System Monitoring**:
- List active recordings with pagination support
- Monitor recording system status and statistics
- **Reservation Management**:
- List, create, update, and delete reservations
- Handle reservation conflicts, skips, and overlaps
- View reservation status summaries and counts
- **Encoding Job Management**:
- List running and queued encoding jobs with progress
- Add new manual encoding jobs for recorded content
- Cancel active or queued encoding jobs
- **Multiple Output Formats**:
- Clean table format for human reading (default)
- JSON output for scripting and automation
Expand Down Expand Up @@ -151,6 +159,56 @@ epgstationctl recordings list --offset=0 --limit=50
epgstationctl recordings list --verbose --half-width=true
```

#### Reservations

```bash
# List all reservations
epgstationctl reserves list

# Filter reservations by type and rule
epgstationctl reserves list --type=normal --rule-id=123

# Show detailed reservation information
epgstationctl reserves show 456

# Create a new reservation
epgstationctl reserves create --program-id=789 --encode-mode1=H.264

# Update reservation settings
epgstationctl reserves update 456 --encode-mode1=H.265 --parent-dir=/recordings

# Delete a reservation
epgstationctl reserves delete 456

# Remove skip status from reservation
epgstationctl reserves unskip 456

# Show reservation status summary
epgstationctl reserves status

# Trigger reservation system update
epgstationctl reserves update-system
```

#### Encoding Jobs

```bash
# List all encoding jobs (running and queued)
epgstationctl encodes list

# Add a new encoding job
epgstationctl encodes add --recorded-id=123 --mode=H.264 --parent-dir=/encoded

# Cancel an encoding job
epgstationctl encodes cancel 789

# Show encoding system status
epgstationctl encodes status

# Add encoding job with options
epgstationctl encodes add --recorded-id=123 --mode=H.265 --remove-original --save-same-dir
```

### Advanced Usage Examples

#### Using Environment Variables
Expand Down Expand Up @@ -248,7 +306,9 @@ epgstationctl/
│ ├── commands/ # CLI command implementations
│ │ ├── channels/ # Channel commands
│ │ ├── programs/ # Program commands
│ │ └── recordings/ # Recording commands
│ │ ├── recordings/ # Recording commands
│ │ ├── reserves/ # Reservation commands
│ │ └── encodes/ # Encoding commands
│ ├── client/ # EPGStation API client wrapper
│ ├── config/ # Configuration management
│ ├── epgstation/ # Generated API client
Expand Down
2 changes: 2 additions & 0 deletions cmd/epgstationctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package main

import (
_ "github.com/miscord-dev/epgstationctl/internal/commands/channels"
_ "github.com/miscord-dev/epgstationctl/internal/commands/encodes"
_ "github.com/miscord-dev/epgstationctl/internal/commands/programs"
_ "github.com/miscord-dev/epgstationctl/internal/commands/recordings"
_ "github.com/miscord-dev/epgstationctl/internal/commands/reserves"
"github.com/miscord-dev/epgstationctl/internal/commands/root"
_ "github.com/miscord-dev/epgstationctl/internal/commands/rules"
)
Expand Down
230 changes: 230 additions & 0 deletions internal/client/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,233 @@ func (c *EPGStationClient) SearchRulesKeyword(params *epgstation.GetRulesKeyword

return &keywords, nil
}

// GetReserves retrieves all reserves with filtering options
func (c *EPGStationClient) GetReserves(params *epgstation.GetReservesParams) (*epgstation.Reserves, error) {
resp, err := c.client.GetReserves(context.Background(), params)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
}

var reserves epgstation.Reserves
if err := parseJSONResponse(resp, &reserves); err != nil {
return nil, err
}

return &reserves, nil
}

// GetReserve retrieves a specific reserve by ID
func (c *EPGStationClient) GetReserve(reserveId int) (*epgstation.ReserveItem, error) {
resp, err := c.client.GetReservesReserveId(context.Background(), reserveId, &epgstation.GetReservesReserveIdParams{})
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
}

var reserve epgstation.ReserveItem
if err := parseJSONResponse(resp, &reserve); err != nil {
return nil, err
}

return &reserve, nil
}

// CreateReserve creates a new manual reserve
func (c *EPGStationClient) CreateReserve(reserveOption epgstation.ManualReserveOption) (*epgstation.AddedReserve, error) {
resp, err := c.client.PostReserves(context.Background(), reserveOption)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusCreated {
return nil, handleErrorResponse(resp)
}

var result epgstation.AddedReserve
if err := parseJSONResponse(resp, &result); err != nil {
return nil, err
}

return &result, nil
}

// UpdateReserve updates an existing reserve
func (c *EPGStationClient) UpdateReserve(reserveId int, reserveOption epgstation.EditManualReserveOption) error {
resp, err := c.client.PutReservesReserveId(context.Background(), reserveId, reserveOption)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return handleErrorResponse(resp)
}

return nil
}

// DeleteReserve deletes a reserve
func (c *EPGStationClient) DeleteReserve(reserveId int) error {
resp, err := c.client.DeleteReservesReserveId(context.Background(), reserveId)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return handleErrorResponse(resp)
}

return nil
}

// UnskipReserve removes skip status from a reserve
func (c *EPGStationClient) UnskipReserve(reserveId int) error {
resp, err := c.client.DeleteReservesReserveIdSkip(context.Background(), reserveId)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return handleErrorResponse(resp)
}

return nil
}

// RemoveOverlapReserve removes overlap status from a reserve
func (c *EPGStationClient) RemoveOverlapReserve(reserveId int) error {
resp, err := c.client.DeleteReservesReserveIdOverlap(context.Background(), reserveId)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return handleErrorResponse(resp)
}

return nil
}

// GetReserveLists gets categorized reserve lists
func (c *EPGStationClient) GetReserveLists(params *epgstation.GetReservesListsParams) (*epgstation.ReserveLists, error) {
resp, err := c.client.GetReservesLists(context.Background(), params)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
}

var lists epgstation.ReserveLists
if err := parseJSONResponse(resp, &lists); err != nil {
return nil, err
}

return &lists, nil
}

// GetReserveCounts gets reserve counts by category
func (c *EPGStationClient) GetReserveCounts() (*epgstation.ReserveCnts, error) {
resp, err := c.client.GetReservesCnts(context.Background())
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
}

var counts epgstation.ReserveCnts
if err := parseJSONResponse(resp, &counts); err != nil {
return nil, err
}

return &counts, nil
}

// UpdateReserveSystem triggers a reserve system update
func (c *EPGStationClient) UpdateReserveSystem() error {
resp, err := c.client.PostReservesUpdate(context.Background())
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return handleErrorResponse(resp)
}

return nil
}

// GetEncodes retrieves encode information (running and queued jobs)
func (c *EPGStationClient) GetEncodes(params *epgstation.GetEncodeParams) (*epgstation.EncodeInfo, error) {
resp, err := c.client.GetEncode(context.Background(), params)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return nil, handleErrorResponse(resp)
}

var encodes epgstation.EncodeInfo
if err := parseJSONResponse(resp, &encodes); err != nil {
return nil, err
}

return &encodes, nil
}

// CreateEncode creates a new manual encode job
func (c *EPGStationClient) CreateEncode(encodeOption epgstation.AddManualEncodeProgramOption) (*epgstation.AddedEncode, error) {
resp, err := c.client.PostEncode(context.Background(), encodeOption)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusCreated {
return nil, handleErrorResponse(resp)
}

var result epgstation.AddedEncode
if err := parseJSONResponse(resp, &result); err != nil {
return nil, err
}

return &result, nil
}

// CancelEncode cancels an encode job
func (c *EPGStationClient) CancelEncode(encodeId int) error {
resp, err := c.client.DeleteEncodeEncodeId(context.Background(), encodeId)
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()

if resp.StatusCode != http.StatusOK {
return handleErrorResponse(resp)
}

return nil
}
Loading
Loading