135 lines
3.1 KiB
Go
135 lines
3.1 KiB
Go
|
package twitter
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/iawia002/annie/downloader"
|
||
|
"github.com/iawia002/annie/extractors"
|
||
|
"github.com/iawia002/annie/request"
|
||
|
"github.com/iawia002/annie/utils"
|
||
|
)
|
||
|
|
||
|
type twitter struct {
|
||
|
Track struct {
|
||
|
URL string `json:"playbackUrl"`
|
||
|
} `json:"track"`
|
||
|
TweetID string
|
||
|
Username string
|
||
|
}
|
||
|
|
||
|
// Extract is the main function for extracting data
|
||
|
func Extract(uri string) ([]downloader.Data, error) {
|
||
|
html, err := request.Get(uri, uri, nil)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
usernames := utils.MatchOneOf(html, `property="og:title"\s+content="(.+)"`)
|
||
|
if usernames == nil || len(usernames) < 2 {
|
||
|
return nil, extractors.ErrURLParseFailed
|
||
|
}
|
||
|
username := usernames[1]
|
||
|
|
||
|
tweetIDs := utils.MatchOneOf(uri, `(status|statuses)/(\d+)`)
|
||
|
if tweetIDs == nil || len(tweetIDs) < 3 {
|
||
|
return nil, extractors.ErrURLParseFailed
|
||
|
}
|
||
|
tweetID := tweetIDs[2]
|
||
|
|
||
|
api := fmt.Sprintf(
|
||
|
"https://api.twitter.com/1.1/videos/tweet/config/%s.json", tweetID,
|
||
|
)
|
||
|
headers := map[string]string{
|
||
|
"Authorization": "Bearer AAAAAAAAAAAAAAAAAAAAAIK1zgAAAAAA2tUWuhGZ2JceoId5GwYWU5GspY4%3DUq7gzFoCZs1QfwGoVdvSac3IniczZEYXIcDyumCauIXpcAPorE",
|
||
|
}
|
||
|
jsonString, err := request.Get(api, uri, headers)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
var twitterData twitter
|
||
|
if err := json.Unmarshal([]byte(jsonString), &twitterData); err != nil {
|
||
|
return nil, extractors.ErrURLParseFailed
|
||
|
}
|
||
|
twitterData.TweetID = tweetID
|
||
|
twitterData.Username = username
|
||
|
extractedData, err := download(twitterData, uri)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return extractedData, nil
|
||
|
}
|
||
|
|
||
|
func download(data twitter, uri string) ([]downloader.Data, error) {
|
||
|
var (
|
||
|
err error
|
||
|
size int64
|
||
|
)
|
||
|
streams := make(map[string]downloader.Stream)
|
||
|
switch {
|
||
|
// if video file is m3u8 and ts
|
||
|
case strings.Contains(data.Track.URL, ".m3u8"):
|
||
|
m3u8urls, err := utils.M3u8URLs(data.Track.URL)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
for index, m3u8 := range m3u8urls {
|
||
|
var totalSize int64
|
||
|
var urls []downloader.URL
|
||
|
ts, err := utils.M3u8URLs(m3u8)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
for _, i := range ts {
|
||
|
size, err := request.Size(i, uri)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
temp := downloader.URL{
|
||
|
URL: i,
|
||
|
Size: size,
|
||
|
Ext: "ts",
|
||
|
}
|
||
|
totalSize += size
|
||
|
urls = append(urls, temp)
|
||
|
}
|
||
|
qualityString := utils.MatchOneOf(m3u8, `/(\d+x\d+)/`)[1]
|
||
|
quality := strconv.Itoa(index + 1)
|
||
|
streams[quality] = downloader.Stream{
|
||
|
Quality: qualityString,
|
||
|
URLs: urls,
|
||
|
Size: totalSize,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if video file is mp4
|
||
|
case strings.Contains(data.Track.URL, ".mp4"):
|
||
|
size, err = request.Size(data.Track.URL, uri)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
urlData := downloader.URL{
|
||
|
URL: data.Track.URL,
|
||
|
Size: size,
|
||
|
Ext: "mp4",
|
||
|
}
|
||
|
streams["default"] = downloader.Stream{
|
||
|
URLs: []downloader.URL{urlData},
|
||
|
Size: size,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return []downloader.Data{
|
||
|
{
|
||
|
Site: "Twitter twitter.com",
|
||
|
Title: fmt.Sprintf("%s %s", data.Username, data.TweetID),
|
||
|
Type: "video",
|
||
|
Streams: streams,
|
||
|
URL: uri,
|
||
|
},
|
||
|
}, nil
|
||
|
}
|