scripts

Utilitity scripts
git clone git://gtms.dev:scripts
Log | Files | Refs

twitch-notifier.go (2866B)


      1 //usr/bin/go run $0 $@; exit $?
      2 package main
      3 
      4 import (
      5 	"encoding/json"
      6 	"flag"
      7 	"fmt"
      8 	"io"
      9 	"log"
     10 	"net/http"
     11 	"strconv"
     12 	"strings"
     13 	"time"
     14 )
     15 
     16 const clientid = "b2cnkgs6ricpfzuimk03xt1vlsia4g"
     17 
     18 var (
     19 	streams = []string{
     20 		"476845395", // "bashbunni",
     21 		// "447179030", // "rwxrob",
     22 		"474725923", // "togglebit",
     23 		"167160215", // "theprimeagen",
     24 		"443849438", // "ashkankiani",
     25 		"71942329",  //  "acegikmo",
     26 		"114257969", // "teej_dv",
     27 		"233334675", // "battlestategames",
     28 		"73570785",  //  "marlliciuss",
     29 		"39661750",  //  "tensterakdary",
     30 		"106013742", // "pestily",
     31 		"423054112", // "jakobychill",
     32 		"63880003",  //  "anton",
     33 		"81463115",  //  "kotton",
     34 		"150900538", // "pehapkari",
     35 	}
     36 
     37 	dunstify = flag.Bool("dunstify", false, "Use dunstify output")
     38 	fresh    = flag.Int("fresh", 0, "Get streams started before N minutes")
     39 )
     40 
     41 type Stream struct {
     42 	Id         json.Number `json:"_id"`
     43 	StreamType string      `json:"stream_type"`
     44 	Viewers    uint        `json:"viewers"`
     45 	CreatedAt  time.Time   `json:"created_at"`
     46 	Channel    Channel
     47 }
     48 
     49 type Channel struct {
     50 	Status string
     51 	Name   string
     52 	Game   string
     53 }
     54 
     55 func main() {
     56 	flag.Parse()
     57 
     58 	req, err := http.NewRequest("GET", "https://api.twitch.tv/kraken/streams?channel="+strings.Join(streams, ","), nil)
     59 	if err != nil {
     60 		log.Fatal(err)
     61 	}
     62 	req.Header.Add("Accept", "application/vnd.twitchtv.v5+json")
     63 	req.Header.Add("Client-ID", clientid)
     64 
     65 	rsp, err := http.DefaultClient.Do(req)
     66 	if err != nil {
     67 		log.Fatal(err)
     68 	}
     69 	defer rsp.Body.Close()
     70 
     71 	bodyraw, err := io.ReadAll(rsp.Body)
     72 	if err != nil {
     73 		log.Fatal(err)
     74 	}
     75 
     76 	var object struct{ Streams []Stream }
     77 	err = json.Unmarshal(bodyraw, &object)
     78 	if err != nil {
     79 		log.Fatal(err)
     80 	}
     81 
     82 	now := time.Now()
     83 	forbiden := make(map[json.Number]bool)
     84 
     85 	if *fresh > 0 {
     86 		duration, _ := time.ParseDuration("-" + strconv.Itoa(*fresh) + "m")
     87 		target := now.Add(duration)
     88 		for _, stream := range object.Streams {
     89 			if stream.CreatedAt.Before(target) {
     90 				forbiden[stream.Id] = true
     91 			}
     92 		}
     93 	}
     94 
     95 	if *dunstify {
     96 		var sb strings.Builder
     97 		for _, stream := range object.Streams {
     98 			if forbiden[stream.Id] {
     99 				continue
    100 			}
    101 			uptime := now.Sub(stream.CreatedAt)
    102 			sb.WriteString(fmt.Sprintf("• <b>%s</b> (%d) - %s\n", stream.Channel.Name, stream.Viewers, fmtDuration(uptime)))
    103 			sb.WriteString(fmt.Sprintf("  %s\n", stream.Channel.Status))
    104 			sb.WriteString(fmt.Sprintf("  <i>%s</i>\n", stream.Channel.Game))
    105 		}
    106 		fmt.Print(sb.String())
    107 	} else {
    108 		for _, stream := range object.Streams {
    109 			if forbiden[stream.Id] {
    110 				continue
    111 			}
    112 			fmt.Printf("%s\n", stream.Channel.Name)
    113 		}
    114 	}
    115 }
    116 
    117 func fmtDuration(d time.Duration) string {
    118 	d = d.Round(time.Minute)
    119 	h := d / time.Hour
    120 	d -= h * time.Hour
    121 	m := d / time.Minute
    122 	return fmt.Sprintf("%02d:%02d", h, m)
    123 }
    124 
    125 func remove(s []Stream, i int) []Stream {
    126 	s[i] = s[len(s)-1]
    127 	return s[:len(s)-1]
    128 }