use statik, add Procfile

This commit is contained in:
chigusa committed 2020-02-04 20:40:44 +08:00
1 parent d68d3b5441
commit 0fe9111d8e
59 files changed
+284 -330

No files matched your search

+11 -4
View File
@@ -10,12 +10,11 @@ $(notdir $(abspath $(wildcard src/cmd/*/))):
@GOOS=$(PLATFORM) \
GOARCH=$(ARCH) \
CGO_ENABLED=0 \
GOFLAGS=$(GOFLAGS) \
UPX_ENABLE=$(UPX_ENABLE) \
./src/hack/build.sh $@
.PHONY: release
release:
release: build-web generate
@./src/hack/release.sh
.PHONY: release-docker
@@ -28,9 +27,17 @@ test:
.PHONY: clean
clean:
@rm -rf bin
@rm -rf bin ./src/webapp/build
@echo "All clean"
.PHONY: generate
generate:
go generate ./...
go generate ./...
.PHONY: build-web
build-web:
cd ./src/webapp && yarn install && yarn build && cd ../../
.PHONY: run
run:
foreman start || exit 0
+2
View File
@@ -0,0 +1,2 @@
frontend: cd ./src/webapp && npm start && cd ../../
backend: go run ./src/cmd/bililive -c config.yml
+1 -6
View File
@@ -1,11 +1,6 @@
rpc:
enable: true
port: :8080
token: ""
tls:
enable: false
cert_file: ""
key_file: ""
bind: :8080
debug: false
interval: 20
out_put_path: /srv/bililive
+4 -9
View File
@@ -1,14 +1,9 @@
rpc:
enable: false
port: 127.0.0.1:8080
token: ""
tls:
enable: false
cert_file: ""
key_file: ""
enable: true
bind: 127.0.0.1:8080
debug: false
interval: 15
out_put_path: ./
out_put_path: /tmp
feature:
use_native_flv_parser: false
live_rooms:
live_rooms:
+1
View File
@@ -14,6 +14,7 @@ require (
github.com/onsi/ginkgo v1.10.1 // indirect
github.com/onsi/gomega v1.7.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rakyll/statik v0.1.6
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b
github.com/sirupsen/logrus v1.0.6-0.20180329225952-778f2e774c72
+2
View File
@@ -29,6 +29,8 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rakyll/statik v0.1.6 h1:uICcfUXpgqtw2VopbIncslhAmE5hwc4g20TEyEENBNs=
github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs=
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4=
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM=
+2 -2
View File
@@ -15,11 +15,11 @@ import (
"github.com/hr3lxphr6j/bililive-go/src/configs"
"github.com/hr3lxphr6j/bililive-go/src/consts"
"github.com/hr3lxphr6j/bililive-go/src/instance"
"github.com/hr3lxphr6j/bililive-go/src/lib/events"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/listeners"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/log"
"github.com/hr3lxphr6j/bililive-go/src/pkg/events"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
"github.com/hr3lxphr6j/bililive-go/src/recorders"
"github.com/hr3lxphr6j/bililive-go/src/servers"
)
+2 -12
View File
@@ -17,11 +17,7 @@ var (
Input = App.Flag("input", "Live room urls").Short('i').Strings()
Conf = App.Flag("config", "Config file.").Short('c').String()
Rpc = App.Flag("enable-rpc", "Enable RPC server.").Default("false").Bool()
RpcAddr = App.Flag("rpc-addr", "RPC server listen port").Default(":8080").String()
RpcToken = App.Flag("rpc-token", "RPC server token.").String()
RpcTLS = App.Flag("enable-rpc-tls", "Enable TLS for RPC server").Bool()
CertFile = App.Flag("rpc-tls-cert-file", "Cert file for TLS on RPC").String()
KeyFile = App.Flag("rpc-tls-key-file", "Key file for TLS on RPC").String()
RpcBind = App.Flag("rpc-bind", "RPC server bind address").Default(":8080").String()
NativeFlvParser = App.Flag("native-flv-parser", "use native flv parser").Default("false").Bool()
)
@@ -33,13 +29,7 @@ func GenConfigFromFlags() *configs.Config {
return &configs.Config{
RPC: configs.RPC{
Enable: *Rpc,
Bind: *RpcAddr,
Token: *RpcToken,
TLS: configs.TLS{
Enable: *RpcTLS,
CertFile: *CertFile,
KeyFile: *KeyFile,
},
Bind: *RpcBind,
},
Debug: *Debug,
Interval: *Interval,
+1 -26
View File
@@ -1,7 +1,6 @@
package configs
import (
"crypto/tls"
"fmt"
"io/ioutil"
"net"
@@ -10,30 +9,9 @@ import (
"gopkg.in/yaml.v2"
)
type TLS struct {
Enable bool `yaml:"enable"`
CertFile string `yaml:"cert_file"`
KeyFile string `yaml:"key_file"`
}
func (t *TLS) Verify() error {
if t == nil {
return nil
}
if !t.Enable {
return nil
}
if _, err := tls.LoadX509KeyPair(t.CertFile, t.KeyFile); err != nil {
return err
}
return nil
}
type RPC struct {
Enable bool `yaml:"enable"`
Bind string `yaml:"port"`
Token string `yaml:"token"`
TLS TLS `yaml:"tls"`
Bind string `yaml:"bind"`
}
func (r *RPC) Verify() error {
@@ -46,9 +24,6 @@ func (r *RPC) Verify() error {
if _, err := net.ResolveTCPAddr("tcp", r.Bind); err != nil {
return err
}
if err := r.TLS.Verify(); err != nil {
return err
}
return nil
}
-9
View File
@@ -15,15 +15,6 @@ func TestNewConfig(t *testing.T) {
}
func TestTLS_Verify(t *testing.T) {
var tls *TLS
assert.NoError(t, tls.Verify())
tls = new(TLS)
assert.NoError(t, tls.Verify())
tls.Enable = true
assert.Error(t, tls.Verify())
}
func TestRPC_Verify(t *testing.T) {
var rpc *RPC
assert.NoError(t, rpc.Verify())
+1 -1
View File
@@ -1,7 +1,7 @@
package listeners
import (
"github.com/hr3lxphr6j/bililive-go/src/lib/events"
"github.com/hr3lxphr6j/bililive-go/src/pkg/events"
)
const (
+1 -1
View File
@@ -9,8 +9,8 @@ import (
"github.com/hr3lxphr6j/bililive-go/src/configs"
"github.com/hr3lxphr6j/bililive-go/src/instance"
"github.com/hr3lxphr6j/bililive-go/src/interfaces"
"github.com/hr3lxphr6j/bililive-go/src/lib/events"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/pkg/events"
)
const (
+2 -2
View File
@@ -11,11 +11,11 @@ import (
"github.com/hr3lxphr6j/bililive-go/src/configs"
"github.com/hr3lxphr6j/bililive-go/src/instance"
"github.com/hr3lxphr6j/bililive-go/src/lib/events"
evtmock "github.com/hr3lxphr6j/bililive-go/src/lib/events/mock"
livepkg "github.com/hr3lxphr6j/bililive-go/src/live"
livemock "github.com/hr3lxphr6j/bililive-go/src/live/mock"
"github.com/hr3lxphr6j/bililive-go/src/log"
"github.com/hr3lxphr6j/bililive-go/src/pkg/events"
evtmock "github.com/hr3lxphr6j/bililive-go/src/pkg/events/mock"
)
func TestRefresh(t *testing.T) {
+2 -2
View File
@@ -6,10 +6,10 @@ import (
"github.com/tidwall/gjson"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
const (
+2 -2
View File
@@ -6,10 +6,10 @@ import (
"github.com/tidwall/gjson"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
const (
+2 -2
View File
@@ -9,15 +9,15 @@ import (
"text/template"
"time"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
"github.com/robertkrimen/otto"
"github.com/satori/go.uuid"
"github.com/tidwall/gjson"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
)
/*
+2 -2
View File
@@ -7,10 +7,10 @@ import (
"github.com/tidwall/gjson"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
const (
+2 -2
View File
@@ -7,10 +7,10 @@ import (
"strings"
"time"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
const (
+1 -1
View File
@@ -5,8 +5,8 @@ import (
"net/url"
"time"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
type BaseLive struct {
+2 -2
View File
@@ -7,10 +7,10 @@ import (
"github.com/tidwall/gjson"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
const (
+2 -2
View File
@@ -4,10 +4,10 @@ import (
"net/url"
"strings"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
const (
+2 -2
View File
@@ -6,10 +6,10 @@ import (
"github.com/tidwall/gjson"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
const (
+1 -1
View File
@@ -8,9 +8,9 @@ import (
"github.com/tidwall/gjson"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
)
const (
+2 -2
View File
@@ -6,10 +6,10 @@ import (
"github.com/tidwall/gjson"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
const (
+2 -2
View File
@@ -8,10 +8,10 @@ import (
"github.com/tidwall/gjson"
"github.com/hr3lxphr6j/bililive-go/src/lib/http"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/live/internal"
"github.com/hr3lxphr6j/bililive-go/src/pkg/http"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
const (
@@ -1,4 +1,4 @@
//go:generate mockgen -package mock -destination mock/mock.go github.com/hr3lxphr6j/bililive-go/src/lib/events Dispatcher
//go:generate mockgen -package mock -destination mock/mock.go github.com/hr3lxphr6j/bililive-go/src/pkg/events Dispatcher
package events
import (
File renamed without changes.
File renamed without changes.
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/hr3lxphr6j/bililive-go/src/lib/events (interfaces: Dispatcher)
// Source: github.com/hr3lxphr6j/bililive-go/src/pkg/events (interfaces: Dispatcher)
// Package mock is a generated GoMock package.
package mock
@@ -7,7 +7,7 @@ package mock
import (
context "context"
gomock "github.com/golang/mock/gomock"
events "github.com/hr3lxphr6j/bililive-go/src/lib/events"
events "github.com/hr3lxphr6j/bililive-go/src/pkg/events"
reflect "reflect"
)
File renamed without changes.
File renamed without changes.
@@ -6,8 +6,8 @@ import (
"os/exec"
"sync"
"github.com/hr3lxphr6j/bililive-go/src/lib/parser"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/pkg/parser"
)
const (
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/hr3lxphr6j/bililive-go/src/lib/parser (interfaces: Parser)
// Source: github.com/hr3lxphr6j/bililive-go/src/pkg/parser (interfaces: Parser)
// Package mock is a generated GoMock package.
package mock
@@ -10,9 +10,9 @@ import (
"os"
"sync"
"github.com/hr3lxphr6j/bililive-go/src/lib/parser"
"github.com/hr3lxphr6j/bililive-go/src/lib/reader"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/pkg/parser"
"github.com/hr3lxphr6j/bililive-go/src/pkg/reader"
)
const (
File renamed without changes.
@@ -1,4 +1,4 @@
//go:generate mockgen -package mock -destination mock/mock.go github.com/hr3lxphr6j/bililive-go/src/lib/parser Parser
//go:generate mockgen -package mock -destination mock/mock.go github.com/hr3lxphr6j/bililive-go/src/pkg/parser Parser
package parser
import (
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1 -1
View File
@@ -1,6 +1,6 @@
package recorders
import "github.com/hr3lxphr6j/bililive-go/src/lib/events"
import "github.com/hr3lxphr6j/bililive-go/src/pkg/events"
const (
RecorderStart events.EventType = "RecorderStart"
+1 -1
View File
@@ -6,9 +6,9 @@ import (
"github.com/hr3lxphr6j/bililive-go/src/instance"
"github.com/hr3lxphr6j/bililive-go/src/interfaces"
"github.com/hr3lxphr6j/bililive-go/src/lib/events"
"github.com/hr3lxphr6j/bililive-go/src/listeners"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/pkg/events"
)
func NewManager(ctx context.Context) Manager {
+5 -5
View File
@@ -18,12 +18,12 @@ import (
"github.com/hr3lxphr6j/bililive-go/src/configs"
"github.com/hr3lxphr6j/bililive-go/src/instance"
"github.com/hr3lxphr6j/bililive-go/src/interfaces"
"github.com/hr3lxphr6j/bililive-go/src/lib/events"
"github.com/hr3lxphr6j/bililive-go/src/lib/parser"
"github.com/hr3lxphr6j/bililive-go/src/lib/parser/ffmpeg"
"github.com/hr3lxphr6j/bililive-go/src/lib/parser/native/flv"
"github.com/hr3lxphr6j/bililive-go/src/lib/utils"
"github.com/hr3lxphr6j/bililive-go/src/live"
"github.com/hr3lxphr6j/bililive-go/src/pkg/events"
"github.com/hr3lxphr6j/bililive-go/src/pkg/parser"
"github.com/hr3lxphr6j/bililive-go/src/pkg/parser/ffmpeg"
"github.com/hr3lxphr6j/bililive-go/src/pkg/parser/native/flv"
"github.com/hr3lxphr6j/bililive-go/src/pkg/utils"
)
const (
+57 -112
View File
@@ -2,7 +2,6 @@ package servers
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
@@ -19,12 +18,7 @@ import (
"github.com/hr3lxphr6j/bililive-go/src/recorders"
)
type CommonResp struct {
ErrNo int `json:"err_no"`
ErrMsg string `json:"err_msg"`
Data interface{} `json:"data"`
}
// FIXME: remove this
func parseInfo(ctx context.Context, l live.Live) *live.Info {
inst := instance.GetInstance(ctx)
obj, _ := inst.Cache.Get(l)
@@ -34,95 +28,69 @@ func parseInfo(ctx context.Context, l live.Live) *live.Info {
return info
}
type liveSlice []*live.Info
func (c liveSlice) Len() int {
return len(c)
}
func (c liveSlice) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
func (c liveSlice) Less(i, j int) bool {
return c[i].Live.GetLiveId() < c[j].Live.GetLiveId()
}
func getAllLives(writer http.ResponseWriter, r *http.Request) {
inst := instance.GetInstance(r.Context())
info := liveSlice(make([]*live.Info, 0))
lives := liveSlice(make([]*live.Info, 0, 4))
for _, v := range inst.Lives {
info = append(info, parseInfo(r.Context(), v))
}
sort.Sort(info)
resp := CommonResp{
Data: info,
}
if b, err := json.Marshal(resp); err == nil {
writer.Write(b)
lives = append(lives, parseInfo(r.Context(), v))
}
sort.Sort(lives)
writeJSON(writer, lives)
}
func getLive(writer http.ResponseWriter, r *http.Request) {
inst := instance.GetInstance(r.Context())
vars := mux.Vars(r)
resp := CommonResp{}
if live, ok := inst.Lives[live.ID(vars["id"])]; ok {
resp.Data = parseInfo(r.Context(), live)
} else {
resp.ErrNo = 404
resp.ErrMsg = fmt.Sprintf("live id: %s can not find", vars["id"])
writer.WriteHeader(http.StatusNotFound)
}
if resp, err := json.Marshal(resp); err == nil {
writer.Write(resp)
live, ok := inst.Lives[live.ID(vars["id"])]
if !ok {
writeMsg(writer, http.StatusNotFound, fmt.Sprintf("live id: %s can not find", vars["id"]))
return
}
writeJSON(writer, parseInfo(r.Context(), live))
}
func parseLiveAction(writer http.ResponseWriter, r *http.Request) {
inst := instance.GetInstance(r.Context())
vars := mux.Vars(r)
resp := CommonResp{}
if live, ok := inst.Lives[live.ID(vars["id"])]; ok {
switch vars["action"] {
case "start":
inst.ListenerManager.(listeners.Manager).AddListener(r.Context(), live)
resp.Data = parseInfo(r.Context(), live)
case "stop":
inst.ListenerManager.(listeners.Manager).RemoveListener(r.Context(), live.GetLiveId())
resp.Data = parseInfo(r.Context(), live)
default:
resp.ErrNo = 400
resp.ErrMsg = fmt.Sprintf("invalid Action: %s", vars["action"])
writer.WriteHeader(http.StatusBadRequest)
live, ok := inst.Lives[live.ID(vars["id"])]
if !ok {
writeMsg(writer, http.StatusNotFound, fmt.Sprintf("live id: %s can not find", vars["id"]))
return
}
switch vars["action"] {
case "start":
if err := inst.ListenerManager.(listeners.Manager).AddListener(r.Context(), live); err != nil {
writeMsg(writer, http.StatusBadRequest, err.Error())
return
}
} else {
resp.ErrNo = 404
resp.ErrMsg = fmt.Sprintf("live id: %s can not find", vars["id"])
writer.WriteHeader(http.StatusNotFound)
case "stop":
if err := inst.ListenerManager.(listeners.Manager).RemoveListener(r.Context(), live.GetLiveId()); err != nil {
writeMsg(writer, http.StatusBadRequest, err.Error())
return
}
default:
writeMsg(writer, http.StatusBadRequest, fmt.Sprintf("invalid Action: %s", vars["action"]))
return
}
if resp, err := json.Marshal(resp); err == nil {
writer.Write(resp)
}
writeJSON(writer, parseInfo(r.Context(), live))
}
/* Post data example
{
"lives": [
{
"url": "http://live.bilibili.com/1030",
"listen": true
},
{
"url": "https://live.bilibili.com/493",
"listen": true
}
]
}
[
{
"url": "http://live.bilibili.com/1030",
"listen": true
},
{
"url": "https://live.bilibili.com/493",
"listen": true
}
]
*/
func addLives(writer http.ResponseWriter, r *http.Request) {
b, _ := ioutil.ReadAll(r.Body)
info := liveSlice(make([]*live.Info, 0))
gjson.GetBytes(b, "lives").ForEach(func(key, value gjson.Result) bool {
gjson.GetBytes(b, "#").ForEach(func(key, value gjson.Result) bool {
isListen := value.Get("listen").Bool()
u, _ := url.Parse(value.Get("url").String())
if live, err := live.New(u, instance.GetInstance(r.Context()).Cache); err == nil {
@@ -138,66 +106,43 @@ func addLives(writer http.ResponseWriter, r *http.Request) {
return true
})
sort.Sort(info)
resp := CommonResp{
Data: info,
}
if resp, err := json.Marshal(resp); err == nil {
writer.Write(resp)
}
writeJSON(writer, info)
}
func getConfig(writer http.ResponseWriter, r *http.Request) {
resp := CommonResp{
Data: instance.GetInstance(r.Context()).Config,
}
if resp, err := json.Marshal(resp); err == nil {
writer.Write(resp)
}
writeJSON(writer, instance.GetInstance(r.Context()).Config)
}
func putConfig(writer http.ResponseWriter, r *http.Request) {
resp := CommonResp{}
configRoom := instance.GetInstance(r.Context()).Config.LiveRooms
configRoom = make([]string, 0)
configRoom = make([]string, 0, 4)
for _, live := range instance.GetInstance(r.Context()).Lives {
configRoom = append(configRoom, live.GetRawUrl())
}
instance.GetInstance(r.Context()).Config.LiveRooms = configRoom
if err := instance.GetInstance(r.Context()).Config.Marshal(); err == nil {
resp.Data = "OK"
} else {
resp.ErrNo = 400
resp.ErrMsg = err.Error()
writer.WriteHeader(http.StatusBadRequest)
}
if resp, err := json.Marshal(resp); err == nil {
writer.Write(resp)
if err := instance.GetInstance(r.Context()).Config.Marshal(); err != nil {
writeMsg(writer, http.StatusBadRequest, err.Error())
return
}
writeMsg(writer, http.StatusOK, "OK")
}
func removeLive(writer http.ResponseWriter, r *http.Request) {
inst := instance.GetInstance(r.Context())
vars := mux.Vars(r)
res := CommonResp{}
if live, ok := inst.Lives[live.ID(vars["id"])]; ok {
inst.ListenerManager.(listeners.Manager).RemoveListener(r.Context(), live.GetLiveId())
delete(inst.Lives, live.GetLiveId())
res.Data = "OK"
} else {
res.ErrNo = 404
res.ErrMsg = fmt.Sprintf("live id: %s can not find", vars["id"])
writer.WriteHeader(http.StatusNotFound)
live, ok := inst.Lives[live.ID(vars["id"])]
if !ok {
writeMsg(writer, http.StatusNotFound, fmt.Sprintf("live id: %s can not find", vars["id"]))
return
}
if resp, err := json.Marshal(res); err == nil {
writer.Write(resp)
if err := inst.ListenerManager.(listeners.Manager).RemoveListener(r.Context(), live.GetLiveId()); err != nil {
writeMsg(writer, http.StatusBadRequest, err.Error())
return
}
delete(inst.Lives, live.GetLiveId())
writeMsg(writer, http.StatusOK, "OK")
}
func getInfo(writer http.ResponseWriter, r *http.Request) {
res := CommonResp{
Data: consts.AppInfo,
}
if resp, err := json.Marshal(res); err == nil {
writer.Write(resp)
}
writeJSON(writer, consts.AppInfo)
}
+33
View File
@@ -0,0 +1,33 @@
package servers
import (
"net/http"
"github.com/hr3lxphr6j/bililive-go/src/instance"
)
func log(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
instance.GetInstance(r.Context()).Logger.WithFields(map[string]interface{}{
"Method": r.Method,
"Path": r.RequestURI,
"RemoteAddr": r.RemoteAddr,
}).Debug("Http Request")
handler.ServeHTTP(w, r)
})
}
func cors(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodOptions:
w.Header().Add("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
w.Header().Add("Access-Control-Allow-Headers", "Authorization")
w.Write(nil)
default:
w.Header().Add("Access-Control-Allow-Origin", "*")
handler.ServeHTTP(w, r)
}
})
}
+23
View File
@@ -0,0 +1,23 @@
package servers
import (
"github.com/hr3lxphr6j/bililive-go/src/live"
)
type commonResp struct {
ErrNo int `json:"err_no"`
ErrMsg string `json:"err_msg"`
Data interface{} `json:"data"`
}
type liveSlice []*live.Info
func (c liveSlice) Len() int {
return len(c)
}
func (c liveSlice) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
func (c liveSlice) Less(i, j int) bool {
return c[i].Live.GetLiveId() < c[j].Live.GetLiveId()
}
+38 -83
View File
@@ -1,98 +1,60 @@
package servers
//go:generate statik -f -src=../webapp/build/
import (
"context"
"encoding/base64"
"fmt"
"net/http"
_ "net/http/pprof"
"strings"
"github.com/gorilla/mux"
"github.com/rakyll/statik/fs"
"github.com/hr3lxphr6j/bililive-go/src/instance"
_ "github.com/hr3lxphr6j/bililive-go/src/servers/statik"
)
const (
apiRouterPrefix = "/api"
)
type Server struct {
server *http.Server
}
var authorization string
func initMux(ctx context.Context) *mux.Router {
m := mux.NewRouter()
m.Use(
// log
func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
instance.GetInstance(ctx).Logger.WithFields(map[string]interface{}{
"Method": r.Method,
"Path": r.RequestURI,
"RemoteAddr": r.RemoteAddr,
}).Debug("Http Request")
handler.ServeHTTP(w, r)
})
},
// context
func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handler.ServeHTTP(w, r.WithContext(context.WithValue(r.Context(), instance.InstanceKey, instance.GetInstance(ctx))))
})
},
// CORS
func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodOptions {
w.Header().Add("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
w.Header().Add("Access-Control-Allow-Headers", "Authorization")
w.Write(nil)
} else {
w.Header().Add("Access-Control-Allow-Origin", "*")
handler.ServeHTTP(w, r)
}
})
},
// Content-Type
func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if prefix := strings.Split(r.RequestURI, "/")[1]; prefix != "files" && prefix != "debug" {
w.Header().Add("Content-Type", "application/json")
}
handler.ServeHTTP(w, r)
})
},
// token verify
func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := instance.GetInstance(ctx).Config.RPC.Token
if authorization == "" {
authorization = fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("token:%s", token))))
}
if token == "" || r.Header.Get("authorization") == authorization || r.FormValue("token") == token {
handler.ServeHTTP(w, r)
} else {
w.WriteHeader(http.StatusForbidden)
w.Write([]byte(`{"err_no":403,"err_msg":"the token is incorrect","data":null}`))
}
})
m.Use(func(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handler.ServeHTTP(w,
r.WithContext(
context.WithValue(
r.Context(),
instance.InstanceKey,
instance.GetInstance(ctx),
),
),
)
})
// api
m.HandleFunc("/info", getInfo).Methods("GET", "OPTIONS")
m.HandleFunc("/config", getConfig).Methods("GET", "OPTIONS")
m.HandleFunc("/config", putConfig).Methods("PUT", "OPTIONS")
m.HandleFunc("/lives", getAllLives).Methods("GET", "OPTIONS")
m.HandleFunc("/lives", addLives).Methods("POST", "OPTIONS")
m.HandleFunc("/lives/{id}", getLive).Methods("GET", "OPTIONS")
m.HandleFunc("/lives/{id}", removeLive).Methods("DELETE", "OPTIONS")
m.HandleFunc("/lives/{id}/{action}", parseLiveAction).Methods("GET", "OPTIONS")
}, log)
// file server
m.PathPrefix("/files/").Handler(http.StripPrefix("/files/", http.FileServer(http.Dir(instance.GetInstance(ctx).Config.OutPutPath))))
// api router
apiRoute := m.PathPrefix(apiRouterPrefix).Subrouter()
apiRoute.Use(cors)
apiRoute.HandleFunc("/info", getInfo).Methods("GET", "OPTIONS")
apiRoute.HandleFunc("/config", getConfig).Methods("GET", "OPTIONS")
apiRoute.HandleFunc("/config", putConfig).Methods("PUT", "OPTIONS")
apiRoute.HandleFunc("/lives", getAllLives).Methods("GET", "OPTIONS")
apiRoute.HandleFunc("/lives", addLives).Methods("POST", "OPTIONS")
apiRoute.HandleFunc("/lives/{id}", getLive).Methods("GET", "OPTIONS")
apiRoute.HandleFunc("/lives/{id}", removeLive).Methods("DELETE", "OPTIONS")
apiRoute.HandleFunc("/lives/{id}/{action}", parseLiveAction).Methods("GET", "OPTIONS")
statikFS, err := fs.New()
if err != nil {
instance.GetInstance(ctx).Logger.Fatal(err)
}
m.PathPrefix("/").Handler(http.FileServer(statikFS))
// pprof
if instance.GetInstance(ctx).Config.Debug {
@@ -116,15 +78,8 @@ func NewServer(ctx context.Context) *Server {
func (s *Server) Start(ctx context.Context) error {
inst := instance.GetInstance(ctx)
inst.WaitGroup.Add(1)
config := inst.Config
go func() {
var err error
if config.RPC.TLS.Enable {
err = s.server.ListenAndServeTLS(config.RPC.TLS.CertFile, config.RPC.TLS.KeyFile)
} else {
err = s.server.ListenAndServe()
}
switch err {
switch err := s.server.ListenAndServe(); err {
case nil, http.ErrServerClosed:
default:
inst.Logger.Error(err)
+13
View File
@@ -0,0 +1,13 @@
// Code generated by statik. DO NOT EDIT.
// Package statik contains static assets.
package statik
import (
"github.com/rakyll/statik/fs"
)
func init() {
data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x89cDP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00 \x00asset-manifest.jsonUT\x05\x00\x01cc9^\xac\x94;O\xc30\x14\x85\xf7\xfc\n+3M\x9dG\xdd\x84\x15u@B,\x8c\x88\xc1\xf1Cu\xda\xb8\x95\xed\xf2\x10\xea\x7fG\x8eRp\x12\xa7X\x88\xd1\xee\xf9\xce\xbd\xf7\xdc:\x9f\x11\x001\x17{\xa6\xe3[`\x0f\x00\xc4-\x162!\xda\xde\xc4Km\xb0\x11dI\xb4^v\xf7(\xaby\x9e\x91uB\xb6'\xb9\xebd7\x0e\xd6\x0c\xa8\xa6\x87\xf2uZAT\xc1\x1ej\xc6L\xd2\xe2c\x10\xd7 {V\x9d\xa4\x11-[\xf8\xeb\x0e~\x85YQ\xe5\x88b\xa7\xf2\x88\xf6t0\xe7\xe0\xf6\xe0\xa4\x93%\x9c\x975Ep\xe5D3J\xd0\xab\x19Z5VU\x92\xb4\xa44\xad\x7f\xf2\x1a\xb6\xe6S\x84\xd8x\xa6\x9cS\xf5vBR\xf6\x9elM\xbb\xef8\xe7\xd8\x0b\x8e\x8a\x11L\xb66&)8\xd3&)8\xa3\x15\")\x82E\x81R\xbe\xaaS\xb4\xcaQQ\xb0\xaa$\x18\xc2\xfc2\xce\xdf\xc8\xcb\x98L\xbd\n\xc2\x16o\x07\xb5c\xea;\xa1\xc9m\xd8\x9e\xc6\xb9\\\xd5M-g\x1e\x86\xcf\xf5\x9a4h\x83\x0f\xf7w\x9b\xc7\xa7M\xc0\x16/\xca\x08\x80\xb3\xb5\x8e\x994\xea\xe3x\x10\xd2\xd8\xb4\x9e\xc7\xd5~{1\xff\xf2?\x0e\x0eoj7\xf3%\x89\x00x\x89\xce_\x01\x00\x00\xff\xffPK\x07\x08\x98_=\xd4>\x01\x00\x00\xc8\x04\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00jcDP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00 \x00favicon.icoUT\x05\x00\x01)c9^\x00\x86\x03y\xfc\x89PNG\x0d\n\x1a\n\x00\x00\x00\x0dIHDR\x00\x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\x00\x00\x03MIDATx^\xed\x9a1h\x14A\x14\x86\xff\xb7Ic\xa1\xe4\xd6\x94*\n7\x04\x8c\x85\xa0\x8d\xda\xd8\x89\x82vF\x9bX\x08\x11\xb3G A\x0c\xa9\xd4\x14\x82\xad\x84\xdb\xa8 \x886j\x1aAP\xb41\xa2X)\xd8\xc4\xc2=\x8c\x85\x9dd\x13\xb4\x08BnG\xf64\xc7\xdee\xf7foov3\x97\x9d+\x8f\x99\xf7\xde\xff\xcd\xfff\x8e\x9b!\xe4\xfcC9\xd7\x0f\x0d@; \xe7\x04t\x0b\xe4\xdc\x00z\x13\xd4-\xa0[ \xe7\x04t\x0b\xb42\xc0\xceYg\x98s\x9c\x06\xc7\x11\x10v\xa9`\x16\x0e\xcc\x13\xf7\xde\xba\xa5\x81\x1b2\xea\x89t\x80i;O\x01\x9c\x95\x91$\x85\x18\x0b\xae\xc5\x0e\xc8\x88\x1b\n\xa0`;\x1f 8$#AJ1\xd2\x03P\xb0+\x97\x08\xfcnJ\x85w\x1c6\xf5\x16(\xd8\xceC\x02\x86\xeb\x95ro\xda\xf3\x8c\xf9\x9516\xdfq\xf5\x9b\x10\xa0P\xfe: \xa2\x11\x02\xfe\x00\x98v-6\x17,cC\x0b\x98ve\x11\xe0{\xeb\x83\x0c\x0c\xba\x97\xd9\x97M\xa8\xbd\xa3\x94\xfd\xb6s\xc6\x03&\x01\x1c[\x0f\xc4\x81\xca\xb2\xc5\x98\x00\x80\xc3\x83\x03\\\x8bu\xd5Q\xd9o\x7f\x1b\xf0xu\x12\x84\x8ba\x04\x9b\xf5\x848\xa0{\x01\xf8v'\xa2\xab\x00\xfa\xa3\xec#\x05@_y\xf1\xa0AkS \x9c\xaa%\xe2x\xe1\xf1\xde[+\xa5}\x9f;\xf2m\xc2\xc9avO\x0d@M<\xd6>\x80\xb0\xad! \xc7\xaa\x87\xde\xa3YB\x10\xd9\x1d\xc0K\x00'[\xb5t\xdb-`\xda\xcec\x00\xe7\"\x08?q-v>\xe1B\xb65\xcd\xb4\x1d\xffG\x9a\x1da\xf7\x15\x02][\xb2\x8a3\xa6\xdd\xba\xa5\xdb\x070\xeb\xfc\x02\xc7\xf6\xd0j \xbf\xddQ\xb6\xa3-% \x07o8\xad\xd6\xe3\x10=\xe8\xf1p\xf3g\xa9X\xf1\xbf\xca\x16\x00\x80\xacN\x8dfa\x00}'T'\x96\xac\x81gA\xa6\xf2\x01\xa8\xd3\x02\xb1\x8ek\xe9\x00T\xd9\x04E\xc2\xd6] \x1a\xd7\xf6\x1e\xe0\x07n8\x069\xad\x01\xfcu\xd6\xc7\xa0HX\xaa\x00\x12\xee[R\xa7i\x00\x82\xe3M;\xe0?\x01\x91S\x12\xed\x01R\xbd\x9c0\x98H\x98v\x80v\xc0?\x02\"\xa7\xe8\x16hnA\x11\xb1\x84-+}Z\xdc:E\xe3\xb4\x03\xb4\x03\x9a\x08\x88,#\xdd\xcb \x03\xc6\xadS4n\xcb\xb4\x00\x01\xcf\xb9\x81\xa9\xe6\x7f\xb0s\x03\xa0n$\xa2\xdb\xeehq<w?\x84\x1a;\x89V\xc1\xf9\x98[b\xf7\xf3\xe7\x80F\x12\x0b\x00\x06\x83_I\xf9[<\xe1\xbe%u\xda\xc6\xbf\xc4\xf0\n\xc0 Q\x92-\x0b\xc0\x17f\x96\x9d \x184\x0e\xce\xf7D\x81\xd8\xd2\x00|\xd1\xb5\xbb\x02\xaa^\x01\xc7H\x18\x84\x18\x00\xd4\xbf\x1c\xed\x9bq\x8e\x1b=xS\x17\xc8\xf1\xc3-\xb1\xddA\xc1\x89/GU\xbf\x1e7\xef8\xfbQ\xf5\x86@\xc6\xf5\x80\xe09\xd7bCa+\xde\xf6\xf5\xb8\xea\x0f$\xc2D\x12\xe1\xc2\xd2({$\xda\x00C\xe7\x86RS\xff\x89L\xb0\xec\xc8\xd5\x8f\x03\xa4[\x1fI\xd5\xb4q\xe0\xd3\xb2\xc5\x0e\xc7\x11\x1a5\xa6\xe5\xe3\x07\x15\x9f\xc9\xf9W`\x1c\xfc\x1d@\xef\x97\xad\xe2\xbdN\xc4\xfbs\xbb\xea\xf5G\xa7bc\xef\x01i$R5\xa6v\x80\xaa+\x93U]\xda\x01Y\x91V5\x8fv\x80\xaa+\x93U]\xda\x01Y\x91V5\x8fv\x80\xaa+\x93U]\x7f\x01\xae\x14\x19_\x8c\n^\x1e\x00\x00\x00\x00IEND\xaeB`\x82\x01\x00\x00\xff\xffPK\x07\x08\xa4$qJ\x90\x03\x00\x00\x86\x03\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x89cDP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00index.htmlUT\x05\x00\x01cc9^\x8cVQo\xdb6\x10\xfe+2\x87 \"\xc2\xd0r\xba\xb5\xa9-z/{\x1a0t@\xf7&\x08\x05M\x9d\"\xa64)\x90'g\x86\xa3\xff>P\xb2\xec\xb4k\xba\x06\x81M\xf2\xee\xbb\xfbxw\xbcs\xb1\xa8\x9d\xc2c\x07I\x8b{\xb3-\xe2gb\xa4}\x10\x04,\xd9\x16-\xc8z[\xec\x01e\xa2Z\xe9\x03\xa0 =6\xb7\xf7d\xb9-\x8c\xb6\x9f\x13\x0fF\x10\xad\x9c%I\xeb\xa1\x11d\xd9\xc8C\xdcs\xad\\\xd4\x1a\xc1V\xeeA\x90\x83\x86\xa7\xcey$\x89r\x16\xc1\xa2 O\xba\xc6V\xd4p\xd0\nn\xc7\x0d\xd3V\xa3\x96\xe66(i@\xac\xbe\xb2\x81-\xec\xe1V9\xe3\xfc\x0b3?\xe5\xe3\xdf\x97\xac\xf6\xd2\xea\x06\x02^\x98\xcd\x07\xfc18\x1buQ\xa3\x81\xed\xef2\xb4;'}],\xa7\x83\xc9\xc6\x19\x14P\xa2VK\x15\xc2\xf2\x8e7\xcd\xfd\xae~\x9b\xff\xcaU\xdb\xdb\xcf\\\x85@&_\x01\x8f\x06B\x0b\x80\xe4U\xf8^j\xcb\xdf\xde\xed\x9a7w\xea\xdd\xf7-,\xa7\xc0\xef\\}\xdc\x16\xb5>$\xba\x16\xc4;\x87$\x19\xf5\x04iA?\xb4\xb8^\xe5\xf9\xcfQ\xbf\xd6\x87m\x11\x94\xd7\x1dn\x17Mo\x15jg\xb3\x86\x9e\xe6u\x02\x19\xd0S\xe3|v\x90>A\xe6\x99\x15P\xe6\x15s\x02\xcaU\xc5z\x01Line truncated
fs.Register(data)
}
+26
View File
@@ -0,0 +1,26 @@
package servers
import (
"encoding/json"
"net/http"
)
const (
contentType = "Content-Type"
contentTypeJSON = "application/json"
)
func writeMsg(w http.ResponseWriter, code int, msg string) {
w.WriteHeader(code)
_, _ = w.Write([]byte(msg))
}
func writeJSON(w http.ResponseWriter, obj interface{}) {
b, err := json.Marshal(obj)
if err != nil {
writeMsg(w, http.StatusInternalServerError, err.Error())
return
}
w.Header().Set(contentType, contentTypeJSON)
_, _ = w.Write(b)
}
+2 -1
View File
@@ -38,5 +38,6 @@
"last 1 firefox version",
"last 1 safari version"
]
}
},
"proxy": "http://localhost:8080"
}
@@ -69,4 +69,4 @@ class AddRoomDialog extends React.Component<Props> {
}
}
export default AddRoomDialog;
export default AddRoomDialog;
+1 -1
View File
@@ -53,4 +53,4 @@ class RootLayout extends React.Component {
}
}
export default RootLayout;
export default RootLayout;
+8 -9
View File
@@ -37,15 +37,14 @@ class LiveInfo extends React.Component<Props, IState> {
componentDidMount() {
api.getLiveInfo()
.then((rsp: any) => {
const data = rsp.data;
this.setState({
appName: data.app_name,
appVersion: data.app_version,
buildTime: data.build_time,
gitHash: data.git_hash,
pid: data.pid,
platform: data.platform,
goVersion: data.go_version
appName: rsp.app_name,
appVersion: rsp.app_version,
buildTime: rsp.build_time,
gitHash: rsp.git_hash,
pid: rsp.pid,
platform: rsp.platform,
goVersion: rsp.go_version
})
})
}
@@ -74,4 +73,4 @@ class LiveInfo extends React.Component<Props, IState> {
}
}
export default LiveInfo;
export default LiveInfo;
+5 -2
View File
@@ -169,7 +169,10 @@ class LiveList extends React.Component<Props, IState> {
requestListData() {
api.getRoomList()
.then(function (rsp: any) {
return rsp.data.map((item: any, index: number) => {
if (rsp.length == 0) {
return [];
}
return rsp.map((item: any, index: number) => {
//判断标签状态
let tags;
if (item.listening === true) {
@@ -226,4 +229,4 @@ class LiveList extends React.Component<Props, IState> {
};
}
export default LiveList;
export default LiveList;
@@ -19,4 +19,4 @@ class PopDialog extends React.Component<DialogContent> {
}
}
export default PopDialog;
export default PopDialog;
+8 -10
View File
@@ -8,7 +8,7 @@ import Utils from './common';
const utils = new Utils();
const BASE_URL = "";
const BASE_URL = "/api";
class API {
/**
@@ -30,14 +30,12 @@ class API {
* @param url URL
*/
addNewRoom(url: string) {
const reqBody = {
lives: [
{
"url": url,
"listen": true
}
]
};
const reqBody = [
{
"url": url,
"listen": true
}
];
return utils.requestPost(`${BASE_URL}/lives`, reqBody);
}
@@ -74,4 +72,4 @@ class API {
}
export default API;
export default API;
+1 -1
View File
@@ -115,4 +115,4 @@ class Utils {
}
}
export default Utils;
export default Utils;