cmd/stream.go
changeset 0 5abace724584
child 44 6da40ca4534c
equal deleted inserted replaced
-1:000000000000 0:5abace724584
       
     1 // Copyright © 2017 Mikael Berthe <mikael@lilotux.net>
       
     2 //
       
     3 // Licensed under the MIT license.
       
     4 // Please see the LICENSE file is this directory.
       
     5 
       
     6 package cmd
       
     7 
       
     8 import (
       
     9 	"errors"
       
    10 	"io"
       
    11 
       
    12 	"github.com/spf13/cobra"
       
    13 
       
    14 	"github.com/McKael/madon"
       
    15 )
       
    16 
       
    17 /*
       
    18 var streamOpts struct {
       
    19 	local bool
       
    20 }
       
    21 */
       
    22 
       
    23 // streamCmd represents the stream command
       
    24 var streamCmd = &cobra.Command{
       
    25 	Use:   "stream [user|local|public|:HASHTAG]",
       
    26 	Short: "Listen to an event stream",
       
    27 	Long: `
       
    28 The stream command stays connected to the server and listen to a stream of
       
    29 events (user, local or federated).
       
    30 It can also get a hashtag-based stream if the keyword or prefixed with
       
    31 ':' or '#'.`,
       
    32 	Example: `  madonctl stream           # User timeline stream
       
    33   madonctl stream local     # Local timeline stream
       
    34   madonctl stream public    # Public timeline stream
       
    35   madonctl stream :mastodon # Hashtag
       
    36   madonctl stream #madonctl`,
       
    37 	RunE:       streamRunE,
       
    38 	ValidArgs:  []string{"user", "public"},
       
    39 	ArgAliases: []string{"home"},
       
    40 }
       
    41 
       
    42 func init() {
       
    43 	RootCmd.AddCommand(streamCmd)
       
    44 
       
    45 	//streamCmd.Flags().BoolVar(&streamOpts.local, "local", false, "Events from the local instance")
       
    46 }
       
    47 
       
    48 func streamRunE(cmd *cobra.Command, args []string) error {
       
    49 	streamName := "user"
       
    50 	tag := ""
       
    51 
       
    52 	if len(args) > 0 {
       
    53 		if len(args) != 1 {
       
    54 			return errors.New("too many parameters")
       
    55 		}
       
    56 		arg := args[0]
       
    57 		switch arg {
       
    58 		case "", "user":
       
    59 		case "public":
       
    60 			streamName = arg
       
    61 		case "local":
       
    62 			streamName = "public:local"
       
    63 		default:
       
    64 			if arg[0] != ':' && arg[0] != '#' {
       
    65 				return errors.New("invalid argument")
       
    66 			}
       
    67 			streamName = "hashtag"
       
    68 			tag = arg[1:]
       
    69 			if len(tag) == 0 {
       
    70 				return errors.New("empty hashtag")
       
    71 			}
       
    72 		}
       
    73 	}
       
    74 
       
    75 	if err := madonInit(true); err != nil {
       
    76 		return err
       
    77 	}
       
    78 
       
    79 	evChan := make(chan madon.StreamEvent, 10)
       
    80 	stop := make(chan bool)
       
    81 	done := make(chan bool)
       
    82 
       
    83 	// StreamListener(name string, hashTag string, events chan<- madon.StreamEvent, stopCh <-chan bool, doneCh chan<- bool) error
       
    84 	err := gClient.StreamListener(streamName, tag, evChan, stop, done)
       
    85 	if err != nil {
       
    86 		errPrint("Error: %s", err.Error())
       
    87 		return nil
       
    88 	}
       
    89 
       
    90 	p, err := getPrinter()
       
    91 	if err != nil {
       
    92 		close(stop)
       
    93 		<-done
       
    94 		close(evChan)
       
    95 		return err
       
    96 	}
       
    97 
       
    98 LISTEN:
       
    99 	for {
       
   100 		select {
       
   101 		case _, ok := <-done:
       
   102 			if !ok { // done is closed, end of streaming
       
   103 				done = nil
       
   104 				break LISTEN
       
   105 			}
       
   106 		case ev := <-evChan:
       
   107 			switch ev.Event {
       
   108 			case "error":
       
   109 				if ev.Error != nil {
       
   110 					if ev.Error == io.ErrUnexpectedEOF {
       
   111 						errPrint("The stream connection was unexpectedly closed")
       
   112 						continue
       
   113 					}
       
   114 					errPrint("Error event: [%s] %s", ev.Event, ev.Error)
       
   115 					continue
       
   116 				}
       
   117 				errPrint("Event: [%s]", ev.Event)
       
   118 			case "update":
       
   119 				s := ev.Data.(madon.Status)
       
   120 				p.PrintObj(&s, nil, "")
       
   121 				continue
       
   122 			case "notification":
       
   123 				n := ev.Data.(madon.Notification)
       
   124 				p.PrintObj(&n, nil, "")
       
   125 				continue
       
   126 			case "delete":
       
   127 				// TODO PrintObj ?
       
   128 				errPrint("Event: [%s] Status %d was deleted", ev.Event, ev.Data.(int))
       
   129 			default:
       
   130 				errPrint("Unhandled event: [%s] %T", ev.Event, ev.Data)
       
   131 			}
       
   132 		}
       
   133 	}
       
   134 	close(evChan)
       
   135 	return nil
       
   136 }