<commit_before>package streams

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/FederationOfFathers/dashboard/bridge"
	"github.com/FederationOfFathers/dashboard/db"
	"github.com/nlopes/slack"
	"github.com/uber-go/zap"
)

var bplog = zap.New(zap.NewJSONEncoder()).With(zap.String("module", "streams"), zap.String("service", "beam"))

type beamChannelResponse struct {
	Name  string `json:"name"`
	Token string `json:"token"`
	User  struct {
		AvatarUrl string `json:"avatarUrl"`
		Channel   struct {
			ID     int64 `json:"id"`
			Online bool  `json:"online"`
		} `json:"channel"`
	} `json:"user"`
	Type struct {
		Name string `json:"name"`
	} `json:"type"`
}

type beamManifestResponse struct {
	StartedAt string `json:"startedAt"`
}

type Beam struct {
	BeamUsername string
	ChannelID    int64
	Online       bool
	Title        string
	Game         string
	StartedAt    string
	StartedTime  time.Time
	AvatarUrl    string
}

func (b *Beam) Update() error {
	b.Online = false
	b.Game = ""
	b.StartedAt = ""
	var c = new(beamChannelResponse)
	var cURL = fmt.Sprintf("https://mixer.com/api/v1/channels/%s", b.BeamUsername)
	bplog.Info("fetching channel", zap.String("url", cURL))
	chResponse, err := http.Get(cURL)
	if err != nil {
		return err
	}
	defer chResponse.Body.Close()
	if chResponse.StatusCode != 200 {
		return fmt.Errorf("got HTTP %d '%s' for '%s'", chResponse.StatusCode, chResponse.Status, cURL)
	}
	if err := json.NewDecoder(chResponse.Body).Decode(&c); err != nil {
		return err
	}
	if !c.User.Channel.Online {
		return nil
	}
	b.Online = c.User.Channel.Online
	b.ChannelID = c.User.Channel.ID
	b.Game = c.Type.Name
	b.Title = c.Name
	b.BeamUsername = c.Token
	b.AvatarUrl = c.User.AvatarUrl
	var m = new(beamManifestResponse)
	var mURL = fmt.Sprintf("https://mixer.com/api/v1/channels/%d/manifest.light2", b.ChannelID)
	bplog.Info("fetching manifest", zap.String("url", mURL))
	rsp, err := http.Get(mURL)
	if err != nil {
		return err
	}
	defer rsp.Body.Close()
	if rsp.StatusCode == 404 {
		// Stream went offline
		return nil
	}
	if rsp.StatusCode != 200 {
		return fmt.Errorf("got HTTP %d '%s' for '%s'", chResponse.StatusCode, chResponse.Status, mURL)
	}
	if err := json.NewDecoder(rsp.Body).Decode(&m); err != nil {
		return err
	}
	b.StartedAt = m.StartedAt
	b.StartedTime, err = time.Parse(time.RFC3339Nano, m.StartedAt)
	if err != nil {
		return err
	}
	return nil
}

func (b *Beam) startMessage(memberID int) (string, slack.PostMessageParameters, error) {
	var messageParams = slack.NewPostMessageParameters()

	member, err := DB.MemberByID(memberID)
	if err != nil {
		return "", messageParams, err
	}

	user, err := bridge.Data.Slack.User(member.Slack)
	if err != nil {
		return "", messageParams, err
	}

	var playing = b.Game
	if playing == "" {
		playing = "something"
	}

	var chURL = fmt.Sprintf("https://mixer.com/%s", b.BeamUsername)
	messageParams.AsUser = true
	messageParams.Parse = "full"
	messageParams.LinkNames = 1
	messageParams.UnfurlMedia = true
	messageParams.UnfurlLinks = false
	messageParams.EscapeText = false
	messageParams.Attachments = append(messageParams.Attachments, slack.Attachment{
		Fallback:   fmt.Sprintf("Watch %s play %s at %s", user.Profile.RealNameNormalized, playing, chURL),
		Color:      "#1FBAED",
		AuthorIcon: "https://mixer.com/_latest/assets/favicons/favicon-16x16.png",
		AuthorName: "Mixer",
		Title:      fmt.Sprintf("%s playing %s", b.BeamUsername, b.Game),
		TitleLink:  chURL,
		ThumbURL:   b.AvatarUrl,
		Text:       b.Title,<commit_msg>just changing order<commit_after>package streams

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/FederationOfFathers/dashboard/bridge"
	"github.com/FederationOfFathers/dashboard/db"
	"github.com/nlopes/slack"
	"github.com/uber-go/zap"
)

var bplog = zap.New(zap.NewJSONEncoder()).With(zap.String("module", "streams"), zap.String("service", "beam"))

type beamChannelResponse struct {
	Name  string `json:"name"`
	Token string `json:"token"`
	User  struct {
		AvatarUrl string `json:"avatarUrl"`
		Channel   struct {
			ID     int64 `json:"id"`
			Online bool  `json:"online"`
		} `json:"channel"`
	} `json:"user"`
	Type struct {
		Name string `json:"name"`
	} `json:"type"`
}

type beamManifestResponse struct {
	StartedAt string `json:"startedAt"`
}

type Beam struct {
	BeamUsername string
	ChannelID    int64
	Online       bool
	Title        string
	Game         string
	StartedAt    string
	StartedTime  time.Time
	AvatarUrl    string
}

func (b *Beam) Update() error {
	b.Online = false
	b.Game = ""
	b.StartedAt = ""
	var c = new(beamChannelResponse)
	var cURL = fmt.Sprintf("https://mixer.com/api/v1/channels/%s", b.BeamUsername)
	bplog.Info("fetching channel", zap.String("url", cURL))
	chResponse, err := http.Get(cURL)
	if err != nil {
		return err
	}
	defer chResponse.Body.Close()
	if chResponse.StatusCode != 200 {
		return fmt.Errorf("got HTTP %d '%s' for '%s'", chResponse.StatusCode, chResponse.Status, cURL)
	}
	if err := json.NewDecoder(chResponse.Body).Decode(&c); err != nil {
		return err
	}
	if !c.User.Channel.Online {
		return nil
	}
	b.Online = c.User.Channel.Online
	b.ChannelID = c.User.Channel.ID
	b.Game = c.Type.Name
	b.Title = c.Name
	b.BeamUsername = c.Token
	b.AvatarUrl = c.User.AvatarUrl
	var m = new(beamManifestResponse)
	var mURL = fmt.Sprintf("https://mixer.com/api/v1/channels/%d/manifest.light2", b.ChannelID)
	bplog.Info("fetching manifest", zap.String("url", mURL))
	rsp, err := http.Get(mURL)
	if err != nil {
		return err
	}
	defer rsp.Body.Close()
	if rsp.StatusCode == 404 {
		// Stream went offline
		return nil
	}
	if rsp.StatusCode != 200 {
		return fmt.Errorf("got HTTP %d '%s' for '%s'", chResponse.StatusCode, chResponse.Status, mURL)
	}
	if err := json.NewDecoder(rsp.Body).Decode(&m); err != nil {
		return err
	}
	b.StartedAt = m.StartedAt
	b.StartedTime, err = time.Parse(time.RFC3339Nano, m.StartedAt)
	if err != nil {
		return err
	}
	return nil
}

func (b *Beam) startMessage(memberID int) (string, slack.PostMessageParameters, error) {
	var messageParams = slack.NewPostMessageParameters()

	member, err := DB.MemberByID(memberID)
	if err != nil {
		return "", messageParams, err
	}

	user, err := bridge.Data.Slack.User(member.Slack)
	if err != nil {
		return "", messageParams, err
	}

	var playing = b.Game
	if playing == "" {
		playing = "something"
	}

	var chURL = fmt.Sprintf("https://mixer.com/%s", b.BeamUsername)
	messageParams.AsUser = true
	messageParams.Parse = "full"
	messageParams.LinkNames = 1
	messageParams.UnfurlMedia = true
	messageParams.UnfurlLinks = false
	messageParams.EscapeText = false
	messageParams.Attachments = append(messageParams.Attachments, slack.Attachment{
		Fallback:   fmt.Sprintf("Watch %s play %s at %s", user.Profile.RealNameNormalized, playing, chURL),
		Color:      "#1FBAED",
		AuthorName: "Mixer",
		AuthorIcon: "https://mixer.com/_latest/assets/favicons/favicon-16x16.png",
		Title:      fmt.Sprintf("%s playing %s", b.BeamUsername, b.Game),
		TitleLink:  chURL,
		ThumbURL:   b.AvatarUrl,
		Text:       b.Title,
{'fraction_non_alphanumeric': 0.14612775579423404, 'fraction_numerical': 0.007348784624081402, 'mean_word_length': 3.8840579710144927, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4844395', 'n_tokens_mistral': 2705, 'n_tokens_neox': 2610, 'n_words': 567}