Skip to content

Commit

Permalink
增加cookie管理功能
Browse files Browse the repository at this point in the history
  • Loading branch information
murphysking committed Dec 19, 2024
1 parent 488e130 commit bfc23b5
Show file tree
Hide file tree
Showing 8 changed files with 424 additions and 29 deletions.
6 changes: 6 additions & 0 deletions src/live/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ type Info struct {
AudioOnly bool
}

type InfoCookie struct {
Platform_cn_name string
Host string
Cookie string
}

func (i *Info) MarshalJSON() ([]byte, error) {
t := struct {
Id ID `json:"id"`
Expand Down
109 changes: 109 additions & 0 deletions src/servers/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/url"
"os"
"path/filepath"
"regexp"
"sort"
"strings"

Expand Down Expand Up @@ -420,3 +421,111 @@ func getFileInfo(writer http.ResponseWriter, r *http.Request) {

writeJSON(writer, json)
}

func getLiveHostCookie(writer http.ResponseWriter, r *http.Request) {
inst := instance.GetInstance(r.Context())
hostCookieMap := make(map[string]*live.InfoCookie)
keys := make([]string, 0)
for _, v := range inst.Lives {
urltmp, _ := url.Parse(v.GetRawUrl())
if _, ok := hostCookieMap[urltmp.Host]; ok == true {
continue
}
v1, _ := v.GetInfo()
host := urltmp.Host
if cookie, ok := inst.Config.Cookies[host]; ok == true {
tmp := &live.InfoCookie{Platform_cn_name: v1.Live.GetPlatformCNName(), Host: host, Cookie: cookie}
hostCookieMap[host] = tmp
} else {
tmp := &live.InfoCookie{Platform_cn_name: v1.Live.GetPlatformCNName(), Host: host}
hostCookieMap[host] = tmp
}
keys = append(keys, host)
}
sort.Strings(keys)
result := make([]*live.InfoCookie, 0)
for _, v := range keys {
result = append(result, hostCookieMap[v])
}
writeJSON(writer, result)
}

func putLiveHostCookie(writer http.ResponseWriter, r *http.Request) {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
writeJsonWithStatusCode(writer, http.StatusBadRequest, commonResp{
ErrNo: http.StatusBadRequest,
ErrMsg: err.Error(),
})
return
}
ctx := r.Context()
inst := instance.GetInstance(ctx)
data := gjson.ParseBytes(b)

host := data.Get("Host").Str
cookie := data.Get("Cookie").Str
if cookie == "" {

} else {
reg, _ := regexp.Compile(".*=.*")
if !reg.MatchString(cookie) {
writeJsonWithStatusCode(writer, http.StatusBadRequest, commonResp{
ErrNo: http.StatusBadRequest,
ErrMsg: "cookie格式错误",
})
return
}
}
if inst.Config.Cookies == nil {
inst.Config.Cookies = make(map[string]string)
}
inst.Config.Cookies[host] = cookie
for _, v := range inst.Config.LiveRooms {
tmpurl, _ := url.Parse(v.Url)
if tmpurl.Host != host {
continue
}
if _, err := replaceLiveImpl(ctx, v, v.IsListening); err != nil {
writeJsonWithStatusCode(writer, http.StatusBadRequest, commonResp{
ErrNo: http.StatusBadRequest,
ErrMsg: err.Error(),
})
return
}
}
inst.Config.Marshal()
writeJSON(writer, commonResp{
Data: "OK",
})
}

/**
* 此方法会使录制中的直播间中断重新录制,导致产生多个录制文件
*/
func replaceLiveImpl(ctx context.Context, room configs.LiveRoom, isListen bool) (info *live.Info, err error) {
inst := instance.GetInstance(ctx)
urlStr := room.Url
if !strings.HasPrefix(urlStr, "http://") && !strings.HasPrefix(urlStr, "https://") {
urlStr = "https://" + urlStr
}
u, err := url.Parse(urlStr)
if err != nil {
return nil, errors.New("can't parse url: " + urlStr)
}
opts := make([]live.Option, 0)
if v, ok := inst.Config.Cookies[u.Host]; ok {
opts = append(opts, live.WithKVStringCookies(u, v))
}
newLive, err := live.New(u, inst.Cache, opts...)
if err != nil {
return nil, err
}
inst.ListenerManager.(listeners.Manager).RemoveListener(ctx, newLive.GetLiveId())
inst.Lives[newLive.GetLiveId()] = newLive

if isListen {
inst.ListenerManager.(listeners.Manager).AddListener(ctx, newLive)
}
return nil, nil
}
14 changes: 8 additions & 6 deletions src/servers/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ func initMux(ctx context.Context) *mux.Router {
apiRoute.HandleFunc("/lives/{id}", removeLive).Methods("DELETE")
apiRoute.HandleFunc("/lives/{id}/{action}", parseLiveAction).Methods("GET")
apiRoute.HandleFunc("/file/{path:.*}", getFileInfo).Methods("GET")
apiRoute.HandleFunc("/cookies", getLiveHostCookie).Methods("GET")
apiRoute.HandleFunc("/cookies", putLiveHostCookie).Methods("PUT")
apiRoute.Handle("/metrics", promhttp.Handler())

m.PathPrefix("/files/").Handler(
Expand Down Expand Up @@ -79,12 +81,12 @@ func initMux(ctx context.Context) *mux.Router {
}

func CORSMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
h.ServeHTTP(w, r)
})
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
h.ServeHTTP(w, r)
})
}

func NewServer(ctx context.Context) *Server {
Expand Down
3 changes: 3 additions & 0 deletions src/webapp/src/component/edit-cookie/edit-cookie.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#errorinfo{
background-color: #fffbe6;
}
136 changes: 136 additions & 0 deletions src/webapp/src/component/edit-cookie/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { Modal, Input,notification } from 'antd';
import React from 'react';
import API from '../../utils/api';
import './edit-cookie.css'

const api = new API();

interface Props {
refresh?: any
}

const {TextArea} = Input

class EditCookieDialog extends React.Component<Props> {
state = {
ModalText: '请输入Cookie',
visible: false,
confirmLoading: false,
textView: '',
alertVisible:false,
errorInfo:'',
Host:'',
Platform_cn_name:''
};

showModal = (data:any) => {
var tmpcookie = data.Cookie
if(!tmpcookie){
tmpcookie=""
}
this.setState({
ModalText: '请输入Cookie',
visible: true,
confirmLoading: false,
textView:tmpcookie,
alertVisible:false,
errorInfo:'',
Host:data.Host,
Platform_cn_name:data.Platform_cn_name
});
};

handleOk = () => {
this.setState({
ModalText: '正在保存Cookie......',
confirmLoading: true,
});

api.saveCookie({Host:this.state.Host,Cookie:this.state.textView})
.then((rsp) => {
// 保存设置
api.saveSettingsInBackground();
this.setState({
visible: false,
confirmLoading: false,
textView:'',
Host:'',
Platform_cn_name:''
});
this.props.refresh();
notification.open({
message: '保存成功',
});
})
.catch(err => {
alert(`保存Cookie失败:\n${err}`);
this.setState({
visible: false,
confirmLoading: false,
textView:''
});
})
};
handleCancel = () => {
this.setState({
visible: false,
textView:'',
alertVisible:false,
errorInfo:'',
Host:'',
Platform_cn_name:''
});
};

textChange = (e: any) => {
this.setState({
textView: e.target.value,
alertVisible:false,
errorInfo:''
})
let cookiearr = this.state.textView.split(";")
cookiearr.forEach((cookie,index)=>{
if(cookie.indexOf("=")===-1){
this.setState({alertVisible:true,errorInfo:'cookie格式错误'})
return
}
if(cookie.indexOf("expire")>-1){
//可能是cookie过期时间
let value = cookie.split("=")[1]
let tmpdate
if(value.indexOf("-")>-1){
//可能是日期格式
tmpdate = new Date(value)
}else if(value.length===10){
tmpdate = new Date(value+"000")
}else if(value.length===13){
tmpdate = new Date(value)
}
if(tmpdate){
if(tmpdate<new Date()){
this.setState({alertVisible:true,errorInfo:'cookie可能已经过期'})
}
}
}
})
}
render() {
const { visible, confirmLoading, ModalText,textView,alertVisible,errorInfo,
Host,Platform_cn_name} = this.state;
return (
<div>
<Modal
title={"修改"+{Platform_cn_name}+"("+Host+")Cookie"}
visible={visible}
onOk={this.handleOk}
confirmLoading={confirmLoading}
onCancel={this.handleCancel}>
<p>{ModalText}</p>
<TextArea autoSize={{ minRows: 2, maxRows: 6 }} value={textView} placeholder="请输入Cookie" onChange={this.textChange} allowClear />
<div id="errorinfo" className={alertVisible?'word-style':'word-style:hide'}>{errorInfo}</div>
</Modal>
</div>
);
}
}
export default EditCookieDialog;
Loading

0 comments on commit bfc23b5

Please sign in to comment.