forked from iawia002/lux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Bitchute extractor (iawia002#1368)
* Add bitchute extractor * Update README.md --------- Co-authored-by: Xinzhao Xu <[email protected]>
- Loading branch information
Showing
5 changed files
with
176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]) | ||
}) | ||
} | ||
} |