First pass at YP registration/configuration (#209)
* Spike: Ping YP service with instance details * WIP: Add to the config to support YP * Add YP response endpoint * Handle YP errors. Use config. Off by default * Show message about YP support on launch * Add animated gif preview when generating thumb * Increase quality of preview gif and only create it if YP is enabled * Do not allow re-registration by clearing the key * Make large and small logos actually structured * Change log level * Fix default YP service URL * Point to default hostname * Set default value for YP to false
This commit is contained in:
0
yp/README.md
Normal file
0
yp/README.md
Normal file
46
yp/api.go
Normal file
46
yp/api.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package yp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/gabek/owncast/config"
|
||||
"github.com/gabek/owncast/utils"
|
||||
)
|
||||
|
||||
type ypDetailsResponse struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Logo string `json:"logo"`
|
||||
NSFW bool `json:"nsfw"`
|
||||
Tags []string `json:"tags"`
|
||||
Online bool `json:"online"`
|
||||
ViewerCount int `json:"viewerCount"`
|
||||
OverallMaxViewerCount int `json:"overallMaxViewerCount"`
|
||||
SessionMaxViewerCount int `json:"sessionMaxViewerCount"`
|
||||
|
||||
LastConnectTime utils.NullTime `json:"lastConnectTime"`
|
||||
}
|
||||
|
||||
//GetYPResponse gets the status of the server for YP purposes
|
||||
func GetYPResponse(w http.ResponseWriter, r *http.Request) {
|
||||
status := getStatus()
|
||||
|
||||
response := ypDetailsResponse{
|
||||
Name: config.Config.InstanceDetails.Name,
|
||||
Description: config.Config.InstanceDetails.Summary,
|
||||
Logo: config.Config.InstanceDetails.Logo.Large,
|
||||
NSFW: config.Config.InstanceDetails.NSFW,
|
||||
Tags: config.Config.InstanceDetails.Tags,
|
||||
Online: status.Online,
|
||||
ViewerCount: status.ViewerCount,
|
||||
OverallMaxViewerCount: status.OverallMaxViewerCount,
|
||||
SessionMaxViewerCount: status.SessionMaxViewerCount,
|
||||
LastConnectTime: status.LastConnectTime,
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
json.NewEncoder(w).Encode(response)
|
||||
|
||||
}
|
||||
139
yp/yp.go
Normal file
139
yp/yp.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package yp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gabek/owncast/config"
|
||||
"github.com/gabek/owncast/models"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const pingInterval = 4 * time.Minute
|
||||
|
||||
var getStatus func() models.Status
|
||||
|
||||
//YP is a service for handling listing in the Owncast directory.
|
||||
type YP struct {
|
||||
timer *time.Ticker
|
||||
}
|
||||
|
||||
type ypPingResponse struct {
|
||||
Key string `json:"key"`
|
||||
Success bool `json:"success"`
|
||||
Error string `json:"error"`
|
||||
ErrorCode int `json:"errorCode"`
|
||||
}
|
||||
|
||||
type ypPingRequest struct {
|
||||
Key string `json:"key"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// NewYP creates a new instance of the YP service handler
|
||||
func NewYP(getStatusFunc func() models.Status) *YP {
|
||||
getStatus = getStatusFunc
|
||||
return &YP{}
|
||||
}
|
||||
|
||||
// Start is run when a live stream begins to start pinging YP
|
||||
func (yp *YP) Start() {
|
||||
yp.timer = time.NewTicker(pingInterval)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-yp.timer.C:
|
||||
yp.ping()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
yp.ping()
|
||||
}
|
||||
|
||||
// Stop stops the pinging of YP
|
||||
func (yp *YP) Stop() {
|
||||
yp.timer.Stop()
|
||||
}
|
||||
|
||||
func (yp *YP) ping() {
|
||||
myInstanceURL := config.Config.YP.InstanceURL
|
||||
key := yp.getSavedKey()
|
||||
|
||||
log.Traceln("Pinging YP as: ", config.Config.InstanceDetails.Name)
|
||||
|
||||
request := ypPingRequest{
|
||||
Key: key,
|
||||
URL: myInstanceURL,
|
||||
}
|
||||
|
||||
req, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
|
||||
pingURL := config.Config.GetYPServiceHost() + "/ping"
|
||||
resp, err := http.Post(pingURL, "application/json", bytes.NewBuffer(req))
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
|
||||
pingResponse := ypPingResponse{}
|
||||
json.Unmarshal(body, &pingResponse)
|
||||
|
||||
if !pingResponse.Success {
|
||||
log.Debugln("YP Ping error returned from service:", pingResponse.Error)
|
||||
return
|
||||
}
|
||||
|
||||
if pingResponse.Key != key {
|
||||
yp.writeSavedKey(pingResponse.Key)
|
||||
}
|
||||
}
|
||||
|
||||
func (yp *YP) writeSavedKey(key string) {
|
||||
f, err := os.Create(".yp.key")
|
||||
defer f.Close()
|
||||
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = f.WriteString(key)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (yp *YP) getSavedKey() string {
|
||||
fileBytes, err := ioutil.ReadFile(".yp.key")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(fileBytes)
|
||||
}
|
||||
|
||||
// DisplayInstructions will let the user know they are not in the directory by default and
|
||||
// how they can enable the feature.
|
||||
func DisplayInstructions() {
|
||||
text := "Your instance can be listed on the Owncast directory at http://something.something by enabling YP in your config. Learn more at http://something.something."
|
||||
log.Debugln(text)
|
||||
}
|
||||
Reference in New Issue
Block a user