Skip to content

Commit

Permalink
Add bitchute extractor
Browse files Browse the repository at this point in the history
  • Loading branch information
shavit committed Jun 29, 2024
1 parent 348ae97 commit 249bdb8
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 0 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/stream_bitchute.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: bitchute

on:
push:
paths:
- "extractors/bitchute/*.go"
- ".github/workflows/stream_bitchute.yml"
pull_request:
paths:
- "extractors/bitchute/*.go"
- ".github/workflows/stream_bitchute.yml"
schedule:
# run ci weekly
- cron: "0 0 * * 0"

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
go: ["1.22"]
os: [ubuntu-latest]
name: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}

- name: Test
run: go test -timeout 5m -race -coverpkg=./... -coverprofile=coverage.txt github.com/iawia002/lux/extractors/bitchute
1 change: 1 addition & 0 deletions app/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
_ "github.com/iawia002/lux/extractors/acfun"
_ "github.com/iawia002/lux/extractors/bcy"
_ "github.com/iawia002/lux/extractors/bilibili"
_ "github.com/iawia002/lux/extractors/bitchute"
_ "github.com/iawia002/lux/extractors/douyin"
_ "github.com/iawia002/lux/extractors/douyu"
_ "github.com/iawia002/lux/extractors/eporner"
Expand Down
103 changes: 103 additions & 0 deletions extractors/bitchute/bitchute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package bitchute

import (
"compress/flate"
"compress/gzip"
"fmt"
"io"
"net/http"
"regexp"
"strings"

"github.com/pkg/errors"

"github.com/iawia002/lux/extractors"
"github.com/iawia002/lux/request"
)

func init() {
extractors.Register("bitchute", New())
}

type extractor struct{}

// New returns a bitchute extractor.
func New() extractors.Extractor {
return &extractor{}
}

// Extract is the main function to extract the data.
func (e *extractor) Extract(u string, option extractors.Options) ([]*extractors.Data, error) {
regVideoID := regexp.MustCompile(`/video/([^?/]+)`)
matchVideoID := regVideoID.FindStringSubmatch(u)
if len(matchVideoID) < 2 {
return nil, errors.New("Invalid video URL: Missing video ID parameter")
}
embedURL := fmt.Sprintf("https://www.bitchute.com/api/beta9/embed/?videoID=%s", matchVideoID[1])

res, err := request.Request(http.MethodGet, embedURL, nil, nil)
if err != nil {
return nil, errors.WithStack(err)
}
defer res.Body.Close() // nolint

var reader io.ReadCloser
switch res.Header.Get("Content-Encoding") {
case "gzip":
reader, _ = gzip.NewReader(res.Body)
case "deflate":
reader = flate.NewReader(res.Body)
default:
reader = res.Body
}
defer reader.Close() // nolint

b, err := io.ReadAll(reader)
if err != nil {
return nil, errors.WithStack(err)
}

// There is also an API that provides meta data
// POST https://api.bitchute.com/api/beta9/video {"video_id": <video_id>}
html := string(b)
regMediaURL := regexp.MustCompile(`media_url\s*=\s*['|"](https:\/\/[^.]+\.bitchute\.com\/.*\.mp4)`)
matchMediaURL := regMediaURL.FindStringSubmatch(html)
if len(matchMediaURL) < 2 {
return nil, errors.New("Could not extract media URL from page")
}
mediaURL := matchMediaURL[1]

regVideoName := regexp.MustCompile(`(?m)video_name\s*=\s*["|']\\?"?(.*)["|'];?$`)
matchVideoName := regVideoName.FindStringSubmatch(html)
if len(matchVideoName) < 2 {
return nil, errors.New("Could not extract media name from page")
}
videoName := strings.ReplaceAll(matchVideoName[1], `\"`, "")

streams := make(map[string]*extractors.Stream, 1)
size, err := request.Size(mediaURL, u)
if err != nil {
return nil, errors.WithStack(err)
}
streams["Default"] = &extractors.Stream{
Parts: []*extractors.Part{
{
URL: mediaURL,
Size: size,
Ext: "mp4",
},
},
Size: size,
Quality: "Default",
}

return []*extractors.Data{
{
Site: "Bitchute bitchute.com",
Title: videoName,
Type: extractors.DataTypeVideo,
Streams: streams,
URL: u,
},
}, nil
}
39 changes: 39 additions & 0 deletions extractors/bitchute/bitchute_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package bitchute

import (
"testing"

"github.com/iawia002/lux/extractors"
"github.com/iawia002/lux/test"
)

func TestDownload(t *testing.T) {
tests := []struct {
name string
args test.Args
}{
{
name: "video test 1",
args: test.Args{
URL: "https://www.bitchute.com/video/C17naZ6WlWPo",
Title: "Everybody Dance Now",
Size: 1794720,
},
},
{
name: "video test 2",
args: test.Args{
URL: "https://www.bitchute.com/video/HFgoUz6HrvQd",
Title: "Bear Level 1",
Size: 971698,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
data, err := New().Extract(tt.args.URL, extractors.Options{})
test.CheckError(t, err)
test.Check(t, tt.args, data[0])
})
}
}

0 comments on commit 249bdb8

Please sign in to comment.