mirror of
https://github.com/teacat/chaturbate-dvr.git
synced 2025-10-29 16:59:59 +00:00
updated
color output updated go.mod updated go.sum renamed bucket to temp
This commit is contained in:
parent
f4a7453a3e
commit
be0fba8fa0
16
go.mod
16
go.mod
@ -1,16 +1,20 @@
|
||||
module github.com/YamiOdymel/chaturbate-dvr
|
||||
|
||||
go 1.12
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/elazarl/goproxy v0.0.0-20210801061803-8e322dfb79c4 // indirect
|
||||
github.com/TwiN/go-color v1.1.0
|
||||
github.com/grafov/m3u8 v0.11.1
|
||||
github.com/parnurzeal/gorequest v0.2.16
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/smartystreets/goconvey v1.7.2 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
github.com/teacat/pathx v0.0.0-20201109184104-55ec346a0c6d
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
|
||||
github.com/elazarl/goproxy v0.0.0-20210801061803-8e322dfb79c4 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/smartystreets/goconvey v1.7.2 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
golang.org/x/net v0.0.0-20211109214657-ef0fda0de508 // indirect
|
||||
moul.io/http2curl v1.0.0 // indirect
|
||||
)
|
||||
)
|
||||
9
go.sum
9
go.sum
@ -1,11 +1,12 @@
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/TwiN/go-color v1.1.0 h1:yhLAHgjp2iAxmNjDiVb6Z073NE65yoaPlcki1Q22yyQ=
|
||||
github.com/TwiN/go-color v1.1.0/go.mod h1:aKVf4e1mD4ai2FtPifkDPP5iyoCwiK08YGzGwerjKo0=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/elazarl/goproxy v0.0.0-20210801061803-8e322dfb79c4 h1:lS3P5Nw3oPO05Lk2gFiYUOL3QPaH+fRoI1wFOc4G1UY=
|
||||
github.com/elazarl/goproxy v0.0.0-20210801061803-8e322dfb79c4/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
@ -40,14 +41,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20211109214657-ef0fda0de508 h1:v3NKo+t/Kc3EASxaKZ82lwK6mCf4ZeObQBduYFZHo7c=
|
||||
golang.org/x/net v0.0.0-20211109214657-ef0fda0de508/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
|
||||
42
main.go
42
main.go
@ -13,6 +13,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/TwiN/go-color"
|
||||
"github.com/teacat/pathx"
|
||||
|
||||
"github.com/grafov/m3u8"
|
||||
@ -26,8 +27,8 @@ const chaturbateURL = "https://chaturbate.com/"
|
||||
// retriesAfterOnlined tells the retries for stream when disconnected but not really offlined.
|
||||
var retriesAfterOnlined = 0
|
||||
|
||||
// bucket stores the used segment to prevent fetched the duplicates.
|
||||
var bucket []string
|
||||
// temp stores the used segment to prevent fetched the duplicates.
|
||||
var temp []string
|
||||
|
||||
// segmentIndex is current stored segment index.
|
||||
var segmentIndex int
|
||||
@ -41,9 +42,18 @@ var stripQuota int
|
||||
// path save video
|
||||
const savePath = "video"
|
||||
|
||||
// error/message handler
|
||||
var (
|
||||
errInternal = errors.New("err")
|
||||
errNoUsername = errors.New("chaturbate-dvr: channel username required with `-u [username]` argument")
|
||||
errInternal = errors.New("err")
|
||||
errNoUsername = errors.New("recording: channel username required `-u [USERNAME]` option")
|
||||
errSegRetFail = color.Colorize(color.Red, ("[FAILED] to fetch the video segments after retried, %s might went offline or is in ticket/privat show."))
|
||||
errSegRetFailOnline = color.Colorize(color.Red, ("[FAILED] to fetch the video segments, will try again. [%d/10]"))
|
||||
infoIsOnline = color.Colorize(color.Green, ("[RECORDING] %s is online! start fetching.."))
|
||||
infoBackOnline = color.Colorize(color.Green, ("[INFO] %s is back online!"))
|
||||
infoMergeSegment = color.Colorize(color.Green, ("[INFO] inserting %d segment to the master file. [total: %d]"))
|
||||
infoSkipped = color.Colorize(color.Blue, ("[INFO] skipped %s due to the empty body!\n"))
|
||||
infoNotOnline = color.Colorize(color.Gray, ("[INFO] %s is not online, check again in %d minute(s)"))
|
||||
warningSegment = color.Colorize(color.Yellow, ("[WARNING] cannot find segment %d, will try again. [%d/5]"))
|
||||
)
|
||||
|
||||
// roomDossier is the struct to parse the HLS source from the content body.
|
||||
@ -156,10 +166,10 @@ func watchStream(m3u8Source string, username string, masterFile *os.File, filena
|
||||
// Exit the fetching loop if the channel went offline.
|
||||
if err != nil {
|
||||
if retriesAfterOnlined > 10 {
|
||||
log.Printf("failed to fetch the video segments after retried, %s might went offline.", username)
|
||||
log.Printf(errSegRetFail, username)
|
||||
break
|
||||
} else {
|
||||
log.Printf("failed to fetch the video segments, will try again. (%d/10)", retriesAfterOnlined)
|
||||
log.Printf(errSegRetFailOnline, retriesAfterOnlined)
|
||||
retriesAfterOnlined++
|
||||
// Wait to fetch the next playlist.
|
||||
<-time.After(time.Duration(wait*1000) * time.Millisecond)
|
||||
@ -167,7 +177,7 @@ func watchStream(m3u8Source string, username string, masterFile *os.File, filena
|
||||
}
|
||||
}
|
||||
if retriesAfterOnlined != 0 {
|
||||
log.Printf("%s is back online!", username)
|
||||
log.Printf(infoBackOnline, username)
|
||||
retriesAfterOnlined = 0
|
||||
}
|
||||
for _, v := range chunks {
|
||||
@ -184,12 +194,12 @@ func watchStream(m3u8Source string, username string, masterFile *os.File, filena
|
||||
|
||||
// isDuplicateSegment returns true if the segment is already been fetched.
|
||||
func isDuplicateSegment(URI string) bool {
|
||||
for _, v := range bucket {
|
||||
for _, v := range temp {
|
||||
if URI[len(URI)-10:] == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
bucket = append(bucket, URI[len(URI)-10:])
|
||||
temp = append(temp, URI[len(URI)-10:])
|
||||
return false
|
||||
}
|
||||
|
||||
@ -218,7 +228,7 @@ func combineSegment(master *os.File, filename string) {
|
||||
continue
|
||||
}
|
||||
if retry != 0 {
|
||||
log.Printf("cannot find segment %d, will try again. (%d/5)", index, retry)
|
||||
log.Printf(warningSegment, index, retry)
|
||||
}
|
||||
retry++
|
||||
<-time.After(time.Duration(1*retry) * time.Second)
|
||||
@ -238,9 +248,11 @@ func combineSegment(master *os.File, filename string) {
|
||||
stripIndex++
|
||||
}
|
||||
master.Write(b)
|
||||
log.Printf("inserting %d segment to the master file. (total: %d)", index, segmentIndex)
|
||||
//
|
||||
log.Printf(infoMergeSegment, index, segmentIndex)
|
||||
|
||||
e := os.Remove(fmt.Sprintf("./%s/%s~%d.ts", savePath, filename, delete))
|
||||
//
|
||||
if e != nil {
|
||||
delete--
|
||||
}
|
||||
@ -254,7 +266,7 @@ func fetchSegment(master *os.File, segment *m3u8.MediaSegment, baseURL string, f
|
||||
_, body, _ := gorequest.New().Get(fmt.Sprintf("%s%s", baseURL, segment.URI)).EndBytes()
|
||||
log.Printf("fetching %s (size: %d)\n", segment.URI, len(body))
|
||||
if len(body) == 0 {
|
||||
log.Printf("skipped %s due to the empty body!\n", segment.URI)
|
||||
log.Printf(infoSkipped, segment.URI)
|
||||
return
|
||||
}
|
||||
stripQuota -= len(body)
|
||||
@ -304,15 +316,15 @@ func endpoint(c *cli.Context) error {
|
||||
for {
|
||||
// Capture the stream if the user is currently online.
|
||||
if getOnlineStatus(c.String("username")) {
|
||||
log.Printf("%s is online! fetching...", c.String("username"))
|
||||
log.Printf(infoIsOnline, c.String("username"))
|
||||
capture(c.String("username"))
|
||||
segmentIndex = 0
|
||||
bucket = []string{}
|
||||
temp = []string{}
|
||||
retriesAfterOnlined = 0
|
||||
continue
|
||||
}
|
||||
// Otherwise we keep checking the channel status until the user is online.
|
||||
log.Printf("%s is not online, check again after %d minute(s)...", c.String("username"), c.Int("interval"))
|
||||
log.Printf(infoNotOnline, c.String("username"), c.Int("interval"))
|
||||
<-time.After(time.Minute * time.Duration(c.Int("interval")))
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user