Skip to content

Commit

Permalink
feat: torrent module (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tohrusky authored Jul 17, 2024
1 parent 2d59cc9 commit 6b500e7
Show file tree
Hide file tree
Showing 12 changed files with 559 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,5 @@ tmp

# build files
/nuxbt
/module/torrent/test_save.torrent
/module/torrent/test_torrents/test_save.torrent
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ repos:
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-json
- id: check-yaml
- id: check-xml
Expand Down
16 changes: 15 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
module github.com/TensoRaws/NuxBT-Backend

go 1.21
go 1.22

toolchain go1.22.5

require (
github.com/anacrolix/torrent v1.56.1
github.com/bytedance/sonic v1.11.9
github.com/charmbracelet/log v0.4.0
github.com/eleven26/goss/v4 v4.0.1
Expand All @@ -26,6 +29,9 @@ require (

require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/anacrolix/generics v0.0.2-0.20240227122613-f95486179cab // indirect
github.com/anacrolix/missinggo v1.3.0 // indirect
github.com/anacrolix/missinggo/v2 v2.7.3 // indirect
github.com/aws/aws-sdk-go-v2 v1.20.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11 // indirect
github.com/aws/aws-sdk-go-v2/config v1.18.32 // indirect
Expand All @@ -45,6 +51,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/sts v1.21.1 // indirect
github.com/aws/smithy-go v1.14.0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/charmbracelet/lipgloss v0.11.0 // indirect
Expand All @@ -63,6 +70,7 @@ require (
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect
Expand All @@ -76,10 +84,14 @@ require (
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-varint v0.0.6 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
Expand All @@ -88,6 +100,7 @@ require (
github.com/sagikazarmark/locafero v0.6.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
Expand All @@ -110,4 +123,5 @@ require (
gorm.io/datatypes v1.2.1 // indirect
gorm.io/driver/sqlite v1.5.6 // indirect
gorm.io/hints v1.1.2 // indirect
lukechampine.com/blake3 v1.1.6 // indirect
)
233 changes: 233 additions & 0 deletions go.sum

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions module/torrent/magnet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package torrent

import (
"github.com/anacrolix/torrent/metainfo"
"github.com/anacrolix/torrent/types/infohash"
)

// GetMagnet returns a magnet link for the given torrent hash and trackers.
func GetMagnet(torrentHash string, trackers []string) string {
mag := metainfo.Magnet{
InfoHash: infohash.FromHexString(torrentHash),
Trackers: trackers,
}

return mag.String()
}
19 changes: 19 additions & 0 deletions module/torrent/magnet_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package torrent

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestGetMagnet(t *testing.T) {
mag := GetMagnet("7f3956e5a15b34b62159727c08f944c7e433ad1e", []string{})
assert.Equal(t, "magnet:?xt=urn:btih:7f3956e5a15b34b62159727c08f944c7e433ad1e", mag)
}

func TestGetMagnet2(t *testing.T) {
mag := GetMagnet("7f3956e5a15b34b62159727c08f944c7e433ad1e",
[]string{"http://tracker1.com", "http://tracker2.com"})
assert.Equal(t, "magnet:?xt=urn:btih:7f3956e5a15b34b62159727c08f944c7e433ad1e"+
"&tr=http%3A%2F%2Ftracker1.com&tr=http%3A%2F%2Ftracker2.com", mag)
t.Log(GetMagnet("7f3956e5a15b34b62159727c08f944c7e433ad1e", TRACKER_LIST))
}
1 change: 1 addition & 0 deletions module/torrent/test_torrents/test.torrent
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d10:created by21:qBittorrent v4.6.5.1013:creation datei1721224953e4:infod6:lengthi8211e4:name9:lenna.jpg12:piece lengthi16384e6:pieces20:w��N|�OaO� �+U>Ʃee
1 change: 1 addition & 0 deletions module/torrent/test_torrents/test_folder.torrent
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d10:created by21:qBittorrent v4.6.5.1013:creation datei1721222555e4:infod5:filesld6:lengthi30902e4:pathl3:cxk7:cxk.jpgeed6:lengthi8211e4:pathl9:lenna.jpgeee4:name6:cxkcxk12:piece lengthi16384e6:pieces60:]��!`� $�}Я��&Ȕj�..?�6S�V�N�*>Ek@^O`Gj[A��‘!;i�Iee
Expand Down
111 changes: 111 additions & 0 deletions module/torrent/torrent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package torrent

import (
"crypto/sha1"
"fmt"
"mime/multipart"
"os"

"github.com/anacrolix/torrent/bencode"
)

func NewBitTorrentFileFromMultipart(fh *multipart.FileHeader) (*BitTorrentFile, error) {
fileReader, err := fh.Open()
if err != nil {
return nil, err
}
decoder := bencode.NewDecoder(fileReader)
bencodeTorrent := &BitTorrentFile{}
decodeErr := decoder.Decode(bencodeTorrent)
if decodeErr != nil {
return nil, decodeErr
}

return bencodeTorrent, nil
}

// NewBitTorrentFilePath 通过文件路径创建 BitTorrentFile
func NewBitTorrentFilePath(torrentFilePath string) (*BitTorrentFile, error) {
// io.Reader
fileHeader, err := os.Open(torrentFilePath)
if err != nil {
return nil, err
}
return NewBitTorrentFile(fileHeader)
}

// NewBitTorrentFile 通过文件创建 BitTorrentFile
func NewBitTorrentFile(fileReader *os.File) (*BitTorrentFile, error) {
decoder := bencode.NewDecoder(fileReader)

bencodeTorrent := &BitTorrentFile{}
decodeErr := decoder.Decode(bencodeTorrent)
if decodeErr != nil {
return nil, decodeErr
}
return bencodeTorrent, nil
}

// GetHash 获取 torrent 文件的 hash
func (bencodeTorrent *BitTorrentFile) GetHash() string {
// marshal info part and calculate SHA1
marshaledInfo, marshalErr := bencode.Marshal(bencodeTorrent.Info)
if marshalErr != nil {
return ""
}
return fmt.Sprintf("%x", sha1.Sum(marshaledInfo))
}

// Repack 重新打包 torrent 文件
func (bencodeTorrent *BitTorrentFile) Repack(editStrategy *BitTorrentFileEditStrategy) error {
// Re-pack torrent
if editStrategy.Comment != "" {
bencodeTorrent.Comment = editStrategy.Comment
}
if editStrategy.InfoSource != "" {
bencodeTorrent.Info.Source = editStrategy.InfoSource
}

bencodeTorrent.Info.Private = false

return nil
}

// ConvertToBytes 将 torrent 文件转换为字节
func (bencodeTorrent *BitTorrentFile) ConvertToBytes() ([]byte, error) {
// Marshal the entire torrent file
marshaledTorrent, marshalErr := bencode.Marshal(bencodeTorrent)
if marshalErr != nil {
return nil, marshalErr
}

return marshaledTorrent, nil
}

// SaveTo 将 torrent 文件保存到指定路径
func (bencodeTorrent *BitTorrentFile) SaveTo(filePath string) error {
// Marshal the entire torrent file
marshaledTorrent, marshalErr := bencode.Marshal(bencodeTorrent)
if marshalErr != nil {
return marshalErr
}

// Write to file
file, err := os.Create(filePath)
if err != nil {
return err
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
fmt.Println("Failed to close file", file.Name())
}
}(file)

_, err = file.Write(marshaledTorrent)
if err != nil {
return err
}

return nil
}
98 changes: 98 additions & 0 deletions module/torrent/torrent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package torrent

import (
"testing"

"github.com/stretchr/testify/assert"
)

const testTorrent = "test_torrents/test.torrent"
const testTorrentFolder = "test_torrents/test_folder.torrent"
const testTorrentSave = "test_torrents/test_save.torrent"

func TestTorrentHash(t *testing.T) {
torrentFilePath := testTorrent

torrent, err := NewBitTorrentFilePath(torrentFilePath)
if err != nil {
t.Error(err)
return
}

err = torrent.Repack(&BitTorrentFileEditStrategy{})
if err != nil {
t.Error(err)
return
}
assert.Equal(t, torrent.GetHash(), "7f3956e5a15b34b62159727c08f944c7e433ad1e")
assert.Equal(t, torrent.Info.Name, "lenna.jpg")
}

func TestFolderTorrentHash(t *testing.T) {
torrentFilePath := testTorrentFolder

torrent, err := NewBitTorrentFilePath(torrentFilePath)
if err != nil {
t.Error(err)
return
}

err = torrent.Repack(&BitTorrentFileEditStrategy{})
if err != nil {
t.Error(err)
return
}
assert.Equal(t, torrent.GetHash(), "0f8cd84ebb514a4d6975f217c1df129bba080a01")
assert.Equal(t, torrent.Info.Name, "cxkcxk")
}

func TestRepackTorrent(t *testing.T) {
torrentFilePath := testTorrent

torrent, err := NewBitTorrentFilePath(torrentFilePath)
if err != nil {
t.Error(err)
return
}
comment := "TensoRaws"
infoSource := "https://github.com/TensoRaws"

err = torrent.Repack(&BitTorrentFileEditStrategy{
Comment: comment,
InfoSource: infoSource,
})

if err != nil {
t.Error(err)
return
}

assert.Equal(t, torrent.Comment, comment)
assert.Equal(t, torrent.Info.Source, infoSource)
}

func TestSaveTorrent(t *testing.T) {
torrentFilePath := testTorrent
saveFilePath := testTorrentSave

torrent, err := NewBitTorrentFilePath(torrentFilePath)
if err != nil {
t.Error(err)
return
}

err = torrent.SaveTo(saveFilePath)
if err != nil {
t.Error(err)
return
}

torrent, err = NewBitTorrentFilePath(saveFilePath)
if err != nil {
t.Error(err)
return
}

assert.Equal(t, torrent.GetHash(), "7f3956e5a15b34b62159727c08f944c7e433ad1e")
assert.Equal(t, torrent.Info.Name, "lenna.jpg")
}
37 changes: 37 additions & 0 deletions module/torrent/tracker_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package torrent

var TRACKER_LIST = []string{
"http://1337.abcvg.info:80/announce",

"http://bt.okmp3.ru:2710/announce",

"http://ipv6.rer.lol:6969/announce",

"http://nyaa.tracker.wf:7777/announce",

"http://t.nyaatracker.com:80/announce",

"https://tr.burnabyhighstar.com:443/announce",

"https://tracker.gbitt.info:443/announce",

"https://tracker.gcrenwp.top:443/announce",

"https://tracker.kuroy.me:443/announce",

"https://tracker.lilithraws.org:443/announce",

"https://tracker.loligirl.cn:443/announce",

"https://tracker1.520.jp:443/announce",

"udp://amigacity.xyz:6969/announce",

"udp://bt1.archive.org:6969/announce",

"udp://bt2.archive.org:6969/announce",

"udp://epider.me:6969/announce",

"wss://tracker.openwebtorrent.com:443/announce",
}
Loading

0 comments on commit 6b500e7

Please sign in to comment.