2017-12-26 16:25:10 +01:00
package main
import (
2017-12-29 18:26:13 +01:00
"bufio"
2017-12-26 16:25:10 +01:00
"crypto/sha1"
"encoding/hex"
2017-12-29 18:26:13 +01:00
"fmt"
2018-04-02 12:17:50 +02:00
"github.com/fatih/color"
2018-04-12 16:10:22 +02:00
"github.com/go-ini/ini"
2017-12-29 18:26:13 +01:00
"github.com/zeebo/bencode"
2017-12-26 16:25:10 +01:00
"io"
2017-12-29 18:26:13 +01:00
"io/ioutil"
2018-04-09 15:02:46 +02:00
"launchpad.net/gnuflag"
2017-12-26 21:56:32 +01:00
"log"
2017-12-29 18:26:13 +01:00
"os"
"path/filepath"
2017-12-27 21:43:12 +01:00
"strconv"
2018-04-02 12:17:50 +02:00
"strings"
2018-04-09 15:02:46 +02:00
"time"
2017-12-26 16:25:10 +01:00
)
2018-04-12 00:46:33 +02:00
func ASCIIconvert ( s string ) ( newstring string ) {
for _ , c := range s {
if c > 127 {
2018-04-12 16:10:22 +02:00
newstring = fmt . Sprintf ( "%v\\x%x" , newstring , c )
2018-04-12 00:46:33 +02:00
} else {
2018-04-12 16:10:22 +02:00
newstring = fmt . Sprintf ( "%v%v" , newstring , string ( c ) )
2018-04-12 00:46:33 +02:00
}
}
return
}
2018-04-13 17:16:38 +02:00
func checknotexists ( s string , tags [ ] string ) ( bool , string ) {
2018-04-12 00:46:33 +02:00
for _ , value := range tags {
if value == s {
2018-04-13 17:16:38 +02:00
return false , s
2018-04-12 00:46:33 +02:00
}
}
2018-04-13 17:16:38 +02:00
return true , s
2018-04-12 00:46:33 +02:00
}
2018-04-02 12:17:50 +02:00
func decodetorrentfile ( path string ) ( map [ string ] interface { } , error ) {
2017-12-26 16:25:10 +01:00
dat , err := ioutil . ReadFile ( path )
if err != nil {
2018-04-02 12:17:50 +02:00
return nil , err
2017-12-26 16:25:10 +01:00
}
var torrent map [ string ] interface { }
if err := bencode . DecodeBytes ( [ ] byte ( dat ) , & torrent ) ; err != nil {
2018-04-02 12:17:50 +02:00
return nil , err
2017-12-26 16:25:10 +01:00
}
2018-04-02 12:17:50 +02:00
return torrent , nil
2017-12-26 16:25:10 +01:00
}
2018-04-18 01:33:00 +02:00
func encodetorrentfile ( path string , newstructure * NewTorrentStructure ) error {
2018-04-09 15:02:46 +02:00
if _ , err := os . Stat ( path ) ; os . IsNotExist ( err ) {
2017-12-26 21:56:32 +01:00
os . Create ( path )
}
file , err := os . OpenFile ( path , os . O_WRONLY , 0666 )
if err != nil {
2017-12-28 21:19:46 +01:00
return err
2017-12-26 21:56:32 +01:00
}
defer file . Close ( )
bufferedWriter := bufio . NewWriter ( file )
enc := bencode . NewEncoder ( bufferedWriter )
2017-12-30 16:17:58 +01:00
if err := enc . Encode ( newstructure ) ; err != nil {
2018-04-02 12:17:50 +02:00
return err
2017-12-26 21:56:32 +01:00
}
bufferedWriter . Flush ( )
2017-12-28 21:19:46 +01:00
return nil
2017-12-26 21:56:32 +01:00
}
2017-12-29 18:26:13 +01:00
func fmtime ( path string ) ( mtime int64 ) {
2018-04-06 15:18:06 +02:00
if fi , err := os . Stat ( path ) ; err != nil {
2017-12-28 21:19:46 +01:00
return 0
2018-04-06 15:18:06 +02:00
} else {
mtime = int64 ( fi . ModTime ( ) . Unix ( ) )
return
2017-12-28 21:19:46 +01:00
}
}
2017-12-29 18:26:13 +01:00
func copyfile ( src string , dst string ) error {
2017-12-28 22:43:07 +01:00
originalFile , err := os . Open ( src )
if err != nil {
return err
}
defer originalFile . Close ( )
newFile , err := os . Create ( dst )
if err != nil {
return err
}
defer newFile . Close ( )
if _ , err := io . Copy ( newFile , originalFile ) ; err != nil {
return err
}
2018-04-06 15:18:06 +02:00
if err := newFile . Sync ( ) ; err != nil {
2017-12-28 22:43:07 +01:00
return err
}
return nil
}
2018-04-18 01:33:00 +02:00
type NewTorrentStructure struct {
2018-04-18 13:29:45 +02:00
Active_time int64 ` bencode:"active_time" `
Added_time int64 ` bencode:"added_time" `
Announce_to_dht int64 ` bencode:"announce_to_dht" `
Announce_to_lsd int64 ` bencode:"announce_to_lsd" `
Announce_to_trackers int64 ` bencode:"announce_to_trackers" `
Auto_managed int64 ` bencode:"auto_managed" `
Banned_peers string ` bencode:"banned_peers" `
Banned_peers6 string ` bencode:"banned_peers6" `
Blockperpiece int64 ` bencode:"blocks per piece" `
Completed_time int64 ` bencode:"completed_time" `
Download_rate_limit int64 ` bencode:"download_rate_limit" `
Filesizes [ ] [ ] int64 ` bencode:"file sizes" `
Fileformat string ` bencode:"file-format" `
Fileversion int64 ` bencode:"file-version" `
File_priority [ ] int ` bencode:"file_priority" `
Finished_time int64 ` bencode:"finished_time" `
Infohash string ` bencode:"info-hash" `
Last_seen_complete int64 ` bencode:"last_seen_complete" `
Libtorrentversion string ` bencode:"libtorrent-version" `
Max_connections int64 ` bencode:"max_connections" `
Max_uploads int64 ` bencode:"max_uploads" `
Num_downloaded int64 ` bencode:"num_downloaded" `
Num_incomplete int64 ` bencode:"num_incomplete" `
Mapped_files [ ] string ` bencode:"mapped_files,omitempty" `
Paused int64 ` bencode:"paused" `
Peers string ` bencode:"peers" `
Peers6 string ` bencode:"peers6" `
Pieces [ ] byte ` bencode:"pieces" `
QbthasRootFolder int64 ` bencode:"qBt-hasRootFolder" `
Qbtcategory string ` bencode:"qBt-category" `
Qbtname string ` bencode:"qBt-name" `
QbtqueuePosition int ` bencode:"qBt-queuePosition" `
QbtratioLimit int64 ` bencode:"qBt-ratioLimit" `
QbtsavePath string ` bencode:"qBt-savePath" `
QbtseedStatus int64 ` bencode:"qBt-seedStatus" `
QbtseedingTimeLimit int64 ` bencode:"qBt-seedingTimeLimit" `
Qbttags [ ] string ` bencode:"qBt-tags" `
QbttempPathDisabled int64 ` bencode:"qBt-tempPathDisabled" `
Save_path string ` bencode:"save_path" `
Seed_mode int64 ` bencode:"seed_mode" `
Seeding_time int64 ` bencode:"seeding_time" `
Sequential_download int64 ` bencode:"sequential_download" `
Super_seeding int64 ` bencode:"super_seeding" `
Total_downloaded int64 ` bencode:"total_downloaded" `
Total_uploaded int64 ` bencode:"total_uploaded" `
Trackers [ ] [ ] string ` bencode:"trackers" `
Upload_rate_limit int64 ` bencode:"upload_rate_limit" `
Unfinished * [ ] interface { } ` bencode:"unfinished,omitempty" `
with_label bool
with_tags bool
hasfiles bool
torrentfilepath string
torrentfile map [ string ] interface { }
path string
filesizes float32
sizeandprio [ ] [ ] int64
torrentfilelist [ ] string
npieces int64
piecelenght int64
}
2018-04-18 01:33:00 +02:00
func ( newstructure * NewTorrentStructure ) started ( started int64 ) {
if started == 0 {
newstructure . Paused = 1
newstructure . Auto_managed = 0
newstructure . Announce_to_dht = 0
newstructure . Announce_to_lsd = 0
newstructure . Announce_to_trackers = 0
} else {
newstructure . Paused = 0
newstructure . Auto_managed = 1
newstructure . Announce_to_dht = 1
newstructure . Announce_to_lsd = 1
newstructure . Announce_to_trackers = 1
2018-04-02 12:17:50 +02:00
}
2018-04-18 01:33:00 +02:00
}
func ( newstructure * NewTorrentStructure ) ifcompletedon ( ) {
if newstructure . Completed_time != 0 {
newstructure . Last_seen_complete = int64 ( time . Now ( ) . Unix ( ) )
2018-04-02 12:17:50 +02:00
} else {
2018-04-18 01:33:00 +02:00
newstructure . Unfinished = new ( [ ] interface { } )
2018-04-04 11:55:09 +02:00
}
2018-04-18 01:33:00 +02:00
}
2018-04-18 13:29:45 +02:00
func ( newstructure * NewTorrentStructure ) iftags ( labels [ ] interface { } ) {
if newstructure . with_tags == true && labels != nil {
for _ , label := range labels {
if label != nil {
newstructure . Qbttags = append ( newstructure . Qbttags , label . ( string ) )
}
}
2018-04-10 01:54:58 +02:00
} else {
2018-04-18 13:29:45 +02:00
newstructure . Qbttags = [ ] string { }
2017-12-29 18:26:13 +01:00
}
2018-04-18 01:33:00 +02:00
}
2018-04-18 13:29:45 +02:00
func ( newstructure * NewTorrentStructure ) iflabel ( label interface { } ) {
if newstructure . with_label == true {
switch label . ( type ) {
case nil :
newstructure . Qbtcategory = ""
case string :
newstructure . Qbtcategory = label . ( string )
}
2018-04-02 12:17:50 +02:00
} else {
2018-04-18 01:33:00 +02:00
newstructure . Qbtcategory = ""
2017-12-29 18:26:13 +01:00
}
2018-04-18 01:33:00 +02:00
}
func ( newstructure * NewTorrentStructure ) gettrackers ( trackers [ ] interface { } ) {
for _ , tracker := range trackers {
newstructure . Trackers = append ( newstructure . Trackers , [ ] string { tracker . ( string ) } )
2017-12-29 18:26:13 +01:00
}
2018-04-18 01:33:00 +02:00
}
func ( newstructure * NewTorrentStructure ) prioconvert ( src string ) {
var newprio [ ] int
for _ , c := range [ ] byte ( src ) {
if i := int ( c ) ; ( i == 0 ) || ( i == 128 ) { // if not selected
newprio = append ( newprio , 0 )
} else if ( i == 4 ) || ( i == 8 ) { // if low or normal prio
newprio = append ( newprio , 1 )
} else if i == 12 { // if high prio
newprio = append ( newprio , 6 )
} else {
newprio = append ( newprio , 0 )
}
2017-12-29 18:26:13 +01:00
}
2018-04-18 01:33:00 +02:00
newstructure . File_priority = newprio
}
2018-04-18 13:29:45 +02:00
func ( newstructure * NewTorrentStructure ) fillmissing ( ) {
newstructure . ifcompletedon ( )
newstructure . getnpieces ( )
newstructure . fillsavepaths ( )
2018-04-18 01:33:00 +02:00
if newstructure . Unfinished != nil {
2018-04-18 13:29:45 +02:00
newstructure . Pieces = newstructure . fillnothavefiles ( "0" )
2018-04-03 00:59:50 +02:00
} else {
2018-04-18 13:29:45 +02:00
if newstructure . hasfiles {
newstructure . Pieces = newstructure . fillhavefiles ( )
2018-04-18 01:33:00 +02:00
} else {
2018-04-18 13:29:45 +02:00
newstructure . Pieces = newstructure . fillnothavefiles ( "1" )
2018-04-18 01:33:00 +02:00
}
2018-04-09 23:26:23 +02:00
}
2018-04-18 01:33:00 +02:00
}
2018-04-18 13:29:45 +02:00
func ( newstructure * NewTorrentStructure ) fillsizes ( ) {
newstructure . filesizes = 0
if newstructure . hasfiles {
2018-04-18 01:33:00 +02:00
var filelists [ ] [ ] int64
2018-04-18 13:29:45 +02:00
for num , file := range newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) [ "files" ] . ( [ ] interface { } ) {
2017-12-28 22:10:57 +01:00
var lenght , mtime int64
2018-04-09 23:26:23 +02:00
var filestrings [ ] string
if path , ok := file . ( map [ string ] interface { } ) [ "path.utf-8" ] . ( [ ] interface { } ) ; ok {
for _ , f := range path {
filestrings = append ( filestrings , f . ( string ) )
}
} else {
for _ , f := range file . ( map [ string ] interface { } ) [ "path" ] . ( [ ] interface { } ) {
filestrings = append ( filestrings , f . ( string ) )
}
}
filename := strings . Join ( filestrings , string ( os . PathSeparator ) )
2018-04-18 13:29:45 +02:00
newstructure . torrentfilelist = append ( newstructure . torrentfilelist , filename )
fullpath := newstructure . path + string ( os . PathSeparator ) + filename
newstructure . filesizes += float32 ( file . ( map [ string ] interface { } ) [ "length" ] . ( int64 ) )
2018-04-18 01:33:00 +02:00
if n := newstructure . File_priority [ num ] ; n != 0 {
2017-12-28 22:10:57 +01:00
lenght = file . ( map [ string ] interface { } ) [ "length" ] . ( int64 )
2018-04-18 13:29:45 +02:00
newstructure . sizeandprio = append ( newstructure . sizeandprio , [ ] int64 { lenght , 1 } )
2017-12-28 22:10:57 +01:00
mtime = fmtime ( fullpath )
2017-12-29 18:26:13 +01:00
} else {
lenght , mtime = 0 , 0
2018-04-18 13:29:45 +02:00
newstructure . sizeandprio = append ( newstructure . sizeandprio , [ ] int64 { file . ( map [ string ] interface { } ) [ "length" ] . ( int64 ) , 0 } )
2017-12-29 18:26:13 +01:00
}
2017-12-28 22:10:57 +01:00
flenmtime := [ ] int64 { lenght , mtime }
filelists = append ( filelists , flenmtime )
}
2018-04-18 01:33:00 +02:00
newstructure . Filesizes = filelists
2017-12-28 21:19:46 +01:00
} else {
2018-04-18 13:29:45 +02:00
newstructure . filesizes = float32 ( newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) [ "length" ] . ( int64 ) )
newstructure . Filesizes = [ ] [ ] int64 { { newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) [ "length" ] . ( int64 ) , fmtime ( newstructure . path ) } }
2017-12-28 21:19:46 +01:00
}
2018-04-18 01:33:00 +02:00
}
2018-04-18 13:29:45 +02:00
func ( newstructure * NewTorrentStructure ) getnpieces ( ) {
newstructure . fillsizes ( )
if ( ( newstructure . filesizes / float32 ( newstructure . piecelenght ) ) - float32 ( ( int64 ( newstructure . filesizes ) / newstructure . piecelenght ) ) ) != 0 { // check fraction
newstructure . npieces = int64 ( newstructure . filesizes ) / newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) [ "piece length" ] . ( int64 ) + 1
} else {
newstructure . npieces = int64 ( newstructure . filesizes ) / newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) [ "piece length" ] . ( int64 )
}
}
func ( newstructure * NewTorrentStructure ) fillnothavefiles ( chr string ) [ ] byte {
var newpieces = make ( [ ] byte , 0 , newstructure . npieces )
for i := int64 ( 0 ) ; i < newstructure . npieces ; i ++ {
2018-04-18 01:33:00 +02:00
chr , _ := strconv . Atoi ( chr )
newpieces = append ( newpieces , byte ( chr ) )
2018-04-03 00:59:50 +02:00
}
2018-04-18 01:33:00 +02:00
return newpieces
}
2018-04-18 13:29:45 +02:00
func ( newstructure * NewTorrentStructure ) gethash ( ) ( hash string ) {
torinfo , _ := bencode . EncodeString ( newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) )
h := sha1 . New ( )
io . WriteString ( h , torinfo )
hash = hex . EncodeToString ( h . Sum ( nil ) )
return
}
func ( newstructure * NewTorrentStructure ) fillhavefiles ( ) [ ] byte {
var newpieces = make ( [ ] byte , 0 , newstructure . npieces )
2018-04-18 01:33:00 +02:00
var allocation [ ] [ ] int64
offset := int64 ( 0 )
2018-04-18 13:29:45 +02:00
for _ , pair := range newstructure . sizeandprio {
2018-04-18 01:33:00 +02:00
allocation = append ( allocation , [ ] int64 { offset + 1 , offset + pair [ 0 ] , pair [ 1 ] } )
offset = offset + pair [ 0 ]
}
2018-04-18 13:29:45 +02:00
for i := int64 ( 0 ) ; i < newstructure . npieces ; i ++ {
2018-04-18 01:33:00 +02:00
belongs := false
2018-04-18 13:29:45 +02:00
first , last := i * newstructure . piecelenght , ( i + 1 ) * newstructure . piecelenght
2018-04-18 01:33:00 +02:00
for _ , trio := range allocation {
2018-04-18 13:29:45 +02:00
if ( first >= trio [ 0 ] - newstructure . piecelenght && last <= trio [ 1 ] + newstructure . piecelenght ) && trio [ 2 ] == 1 {
2018-04-18 01:33:00 +02:00
belongs = true
}
}
var chr int
if belongs {
chr , _ = strconv . Atoi ( "1" )
2018-04-10 01:46:16 +02:00
} else {
2018-04-18 01:33:00 +02:00
chr , _ = strconv . Atoi ( "0" )
2018-04-10 01:46:16 +02:00
}
2018-04-18 01:33:00 +02:00
newpieces = append ( newpieces , byte ( chr ) )
2018-04-03 00:59:50 +02:00
}
2018-04-18 01:33:00 +02:00
return newpieces
}
2018-04-18 13:29:45 +02:00
func ( newstructure * NewTorrentStructure ) fillsavepaths ( ) {
2018-04-09 23:26:23 +02:00
var torrentname string
2018-04-18 13:29:45 +02:00
if name , ok := newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) [ "name.utf-8" ] . ( string ) ; ok {
2018-04-09 23:26:23 +02:00
torrentname = name
} else {
2018-04-18 13:29:45 +02:00
torrentname = newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) [ "name" ] . ( string )
2018-04-09 23:26:23 +02:00
}
2018-04-18 13:29:45 +02:00
origpath := newstructure . path
2018-04-10 09:55:50 +02:00
_ , lastdirname := filepath . Split ( strings . Replace ( origpath , string ( os . PathSeparator ) , "/" , - 1 ) )
2018-04-18 13:29:45 +02:00
if newstructure . hasfiles {
2018-04-02 13:54:54 +02:00
if lastdirname == torrentname {
2018-04-18 01:33:00 +02:00
newstructure . QbthasRootFolder = 1
newstructure . Save_path = origpath [ 0 : len ( origpath ) - len ( lastdirname ) ]
2018-04-02 13:54:54 +02:00
} else {
2018-04-18 01:33:00 +02:00
newstructure . QbthasRootFolder = 0
2018-04-18 13:29:45 +02:00
newstructure . Save_path = newstructure . path + string ( os . PathSeparator )
newstructure . Mapped_files = newstructure . torrentfilelist
2018-04-02 13:54:54 +02:00
}
2018-04-02 12:17:50 +02:00
} else {
2018-04-09 22:06:30 +02:00
if lastdirname == torrentname {
2018-04-18 01:33:00 +02:00
newstructure . QbthasRootFolder = 0
newstructure . Save_path = origpath [ 0 : len ( origpath ) - len ( lastdirname ) ]
2018-04-09 22:06:30 +02:00
} else {
2018-04-18 01:33:00 +02:00
newstructure . QbthasRootFolder = 0
2018-04-18 13:29:45 +02:00
newstructure . torrentfilelist = append ( newstructure . torrentfilelist , lastdirname )
newstructure . Mapped_files = newstructure . torrentfilelist
2018-04-18 01:33:00 +02:00
newstructure . Save_path = origpath [ 0 : len ( origpath ) - len ( lastdirname ) ]
2018-04-09 22:06:30 +02:00
}
2018-04-02 12:17:50 +02:00
}
2018-04-18 01:33:00 +02:00
newstructure . QbtsavePath = newstructure . Save_path
}
func logic ( key string , value map [ string ] interface { } , bitdir * string , with_label * bool , with_tags * bool , qbitdir * string , comChannel chan string , position int ) error {
2018-04-18 13:29:45 +02:00
var err error
newstructure := NewTorrentStructure { Active_time : 0 , Added_time : 0 , Announce_to_dht : 0 , Announce_to_lsd : 0 ,
Announce_to_trackers : 0 , Auto_managed : 0 , Completed_time : 0 , Download_rate_limit : - 1 ,
Fileformat : "libtorrent resume file" , Fileversion : 1 , Finished_time : 0 , Last_seen_complete : 0 ,
Libtorrentversion : "1.1.6.0" , Max_connections : 100 , Max_uploads : 100 , Num_downloaded : 0 , Num_incomplete : 0 ,
QbtqueuePosition : 1 , QbtratioLimit : - 2000 , QbtseedStatus : 1 , QbtseedingTimeLimit : - 2 , QbttempPathDisabled : 0 ,
Seed_mode : 0 , Seeding_time : 0 , Sequential_download : 0 , Super_seeding : 0 , Total_downloaded : 0 , Total_uploaded : 0 ,
Upload_rate_limit : 0 , Qbtname : "" , with_label : * with_label , with_tags : * with_tags }
newstructure . torrentfilepath = * bitdir + key
if _ , err = os . Stat ( newstructure . torrentfilepath ) ; os . IsNotExist ( err ) {
comChannel <- fmt . Sprintf ( "Can't find torrent file %v for %v" , newstructure . torrentfilepath , key )
2018-04-18 01:33:00 +02:00
return err
}
2018-04-18 13:29:45 +02:00
newstructure . torrentfile , err = decodetorrentfile ( newstructure . torrentfilepath )
2018-04-18 01:33:00 +02:00
if err != nil {
2018-04-18 13:29:45 +02:00
comChannel <- fmt . Sprintf ( "Can't decode torrent file %v for %v" , newstructure . torrentfilepath , key )
2018-04-18 01:33:00 +02:00
return err
}
2018-04-18 13:29:45 +02:00
if _ , ok := newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) [ "files" ] ; ok {
newstructure . hasfiles = true
2018-04-18 01:33:00 +02:00
} else {
2018-04-18 13:29:45 +02:00
newstructure . hasfiles = false
2018-04-18 01:33:00 +02:00
}
if value [ "path" ] . ( string ) [ len ( value [ "path" ] . ( string ) ) - 1 ] == os . PathSeparator {
2018-04-18 13:29:45 +02:00
newstructure . path = value [ "path" ] . ( string ) [ : len ( value [ "path" ] . ( string ) ) - 1 ]
2018-04-18 01:33:00 +02:00
}
newstructure . Active_time = value [ "runtime" ] . ( int64 )
newstructure . Added_time = value [ "added_on" ] . ( int64 )
newstructure . Completed_time = value [ "completed_on" ] . ( int64 )
newstructure . Infohash = value [ "info" ] . ( string )
newstructure . Seeding_time = value [ "runtime" ] . ( int64 )
newstructure . QbtqueuePosition = position
newstructure . started ( value [ "started" ] . ( int64 ) )
newstructure . Finished_time = int64 ( time . Since ( time . Unix ( value [ "completed_on" ] . ( int64 ) , 0 ) ) . Minutes ( ) )
newstructure . Total_downloaded = value [ "downloaded" ] . ( int64 )
newstructure . Total_uploaded = value [ "uploaded" ] . ( int64 )
newstructure . Upload_rate_limit = value [ "upspeed" ] . ( int64 )
2018-04-18 13:29:45 +02:00
newstructure . iftags ( value [ "labels" ] . ( [ ] interface { } ) )
if value [ "label" ] != nil {
newstructure . iflabel ( value [ "label" ] . ( string ) )
} else {
newstructure . iflabel ( "" )
}
2018-04-18 01:33:00 +02:00
newstructure . gettrackers ( value [ "trackers" ] . ( [ ] interface { } ) )
newstructure . prioconvert ( value [ "prio" ] . ( string ) )
2018-04-18 13:29:45 +02:00
newstructure . Blockperpiece = newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) [ "piece length" ] . ( int64 ) / value [ "blocksize" ] . ( int64 )
newstructure . piecelenght = newstructure . torrentfile [ "info" ] . ( map [ string ] interface { } ) [ "piece length" ] . ( int64 )
newstructure . fillmissing ( )
newbasename := newstructure . gethash ( )
if err = encodetorrentfile ( * qbitdir + newbasename + ".fastresume" , & newstructure ) ; err != nil {
2018-04-02 12:17:50 +02:00
comChannel <- fmt . Sprintf ( "Can't create qBittorrent fastresume file %v" , * qbitdir + newbasename + ".fastresume" )
return err
2017-12-28 22:43:07 +01:00
}
2018-04-18 13:29:45 +02:00
if err = copyfile ( * bitdir + key , * qbitdir + newbasename + ".torrent" ) ; err != nil {
2018-04-02 12:17:50 +02:00
comChannel <- fmt . Sprintf ( "Can't create qBittorrent torrent file %v" , * qbitdir + newbasename + ".torrent" )
return err
2017-12-28 22:43:07 +01:00
}
2018-04-02 13:54:54 +02:00
comChannel <- fmt . Sprintf ( "Sucessfully imported %v" , key )
2018-04-02 12:17:50 +02:00
return nil
2017-12-26 16:25:10 +01:00
}
func main ( ) {
2018-04-12 16:10:22 +02:00
var bitdir , qbitdir , config string
2018-04-09 12:09:59 +02:00
var with_label , with_tags bool = true , true
var without_label , without_tags bool
2018-04-12 16:10:22 +02:00
gnuflag . StringVar ( & bitdir , "source" , ( os . Getenv ( "APPDATA" ) + "\\uTorrent\\" ) , "Source directory that contains resume.dat and torrents files" )
gnuflag . StringVar ( & bitdir , "s" , ( os . Getenv ( "APPDATA" ) + "\\uTorrent\\" ) , "Source directory that contains resume.dat and torrents files" )
2018-04-09 12:09:59 +02:00
gnuflag . StringVar ( & qbitdir , "destination" , ( os . Getenv ( "LOCALAPPDATA" ) + "\\qBittorrent\\BT_backup\\" ) , "Destination directory BT_backup (as default)" )
gnuflag . StringVar ( & qbitdir , "d" , ( os . Getenv ( "LOCALAPPDATA" ) + "\\qBittorrent\\BT_backup\\" ) , "Destination directory BT_backup (as default)" )
2018-04-12 16:10:22 +02:00
gnuflag . StringVar ( & config , "qconfig" , ( os . Getenv ( "APPDATA" ) + "\\qBittorrent\\qBittorrent.ini" ) , "qBittorrent config files (for write tags)" )
gnuflag . StringVar ( & config , "c" , ( os . Getenv ( "APPDATA" ) + "\\qBittorrent\\qBittorrent.ini" ) , "qBittorrent config files (for write tags)" )
2018-04-09 14:51:56 +02:00
gnuflag . BoolVar ( & without_label , "without-labels" , false , "Do not export/import labels" )
gnuflag . BoolVar ( & without_tags , "without-tags" , false , "Do not export/import tags" )
2018-04-09 12:09:59 +02:00
gnuflag . Parse ( true )
if without_label {
with_label = false
}
if without_tags {
with_tags = false
}
if bitdir [ len ( bitdir ) - 1 ] != os . PathSeparator {
bitdir += string ( os . PathSeparator )
}
if qbitdir [ len ( qbitdir ) - 1 ] != os . PathSeparator {
qbitdir += string ( os . PathSeparator )
}
2018-04-02 12:17:50 +02:00
if _ , err := os . Stat ( bitdir ) ; os . IsNotExist ( err ) {
log . Println ( "Can't find uTorrent\\Bittorrent folder" )
time . Sleep ( 30 * time . Second )
os . Exit ( 1 )
}
if _ , err := os . Stat ( qbitdir ) ; os . IsNotExist ( err ) {
log . Println ( "Can't find qBittorrent folder" )
time . Sleep ( 30 * time . Second )
os . Exit ( 1 )
}
resumefilepath := bitdir + "resume.dat"
if _ , err := os . Stat ( resumefilepath ) ; os . IsNotExist ( err ) {
log . Println ( "Can't find uTorrent\\Bittorrent resume file" )
time . Sleep ( 30 * time . Second )
os . Exit ( 1 )
}
resumefile , err := decodetorrentfile ( resumefilepath )
if err != nil {
log . Println ( "Can't decode uTorrent\\Bittorrent resume file" )
time . Sleep ( 30 * time . Second )
os . Exit ( 1 )
}
2018-04-12 16:10:22 +02:00
if with_tags == true {
if _ , err := os . Stat ( config ) ; os . IsNotExist ( err ) {
fmt . Println ( "Can not read qBittorrent config file. Try run and close qBittorrent if you have not done so already, or specify the path explicitly or do not import tags" )
time . Sleep ( 30 * time . Second )
os . Exit ( 1 )
}
2018-04-12 00:46:33 +02:00
}
2018-04-09 16:42:21 +02:00
color . Green ( "It will be performed processing from directory %v to directory %v\n" , bitdir , qbitdir )
2018-04-12 22:13:17 +02:00
color . HiRed ( "Check that the qBittorrent is turned off and the directory %v and config %v is backed up.\n\n" , qbitdir , config )
2018-04-02 12:17:50 +02:00
fmt . Println ( "Press Enter to start" )
2018-04-18 13:29:45 +02:00
//fmt.Scanln()
2018-04-02 13:54:54 +02:00
fmt . Println ( "Started" )
2018-04-11 19:49:24 +02:00
totaljobs := len ( resumefile ) - 2
numjob := 1
2018-04-12 16:10:22 +02:00
var oldtags string
var newtags [ ] string
2018-04-02 12:17:50 +02:00
comChannel := make ( chan string , totaljobs )
for key , value := range resumefile {
2017-12-27 22:00:50 +01:00
if key != ".fileguard" && key != "rec" {
2018-04-12 16:10:22 +02:00
if with_tags == true {
for _ , label := range value . ( map [ string ] interface { } ) [ "labels" ] . ( [ ] interface { } ) {
if len ( label . ( string ) ) > 0 {
2018-04-13 17:16:38 +02:00
if ok , tag := checknotexists ( ASCIIconvert ( label . ( string ) ) , newtags ) ; ok {
newtags = append ( newtags , tag )
2018-04-12 16:10:22 +02:00
}
}
}
}
go logic ( key , value . ( map [ string ] interface { } ) , & bitdir , & with_label , & with_tags , & qbitdir , comChannel , totaljobs )
2017-12-26 16:25:10 +01:00
}
}
2018-04-02 12:17:50 +02:00
for message := range comChannel {
fmt . Printf ( "%v/%v %v \n" , numjob , totaljobs , message )
numjob ++
2018-04-09 15:02:46 +02:00
if numjob - 1 == totaljobs {
2018-04-04 12:00:46 +02:00
break
}
2018-04-02 12:17:50 +02:00
}
2018-04-12 16:10:22 +02:00
if with_tags == true {
cfg , err := ini . Load ( config )
ini . PrettyFormat = false
ini . PrettySection = false
if err != nil {
fmt . Println ( "Can not read qBittorrent config file. Try to specify the path explicitly or do not import tags" )
time . Sleep ( 30 * time . Second )
os . Exit ( 1 )
}
if _ , err := cfg . GetSection ( "BitTorrent" ) ; err != nil {
cfg . NewSection ( "BitTorrent" )
2018-04-12 00:46:33 +02:00
2018-04-12 16:10:22 +02:00
//Dirty hack for section order. Sorry
kv := cfg . Section ( "Network" ) . KeysHash ( )
cfg . DeleteSection ( "Network" )
cfg . NewSection ( "Network" )
for key , value := range kv {
cfg . Section ( "Network" ) . NewKey ( key , value )
}
//End of dirty hack
}
if cfg . Section ( "BitTorrent" ) . HasKey ( "Session\\Tags" ) {
oldtags = cfg . Section ( "BitTorrent" ) . Key ( "Session\\Tags" ) . String ( )
for _ , tag := range strings . Split ( oldtags , ", " ) {
2018-04-13 17:16:38 +02:00
if ok , t := checknotexists ( tag , newtags ) ; ok {
newtags = append ( newtags , t )
2018-04-12 16:10:22 +02:00
}
}
cfg . Section ( "BitTorrent" ) . Key ( "Session\\Tags" ) . SetValue ( strings . Join ( newtags , ", " ) )
} else {
cfg . Section ( "BitTorrent" ) . NewKey ( "Session\\Tags" , strings . Join ( newtags , ", " ) )
2018-04-12 00:46:33 +02:00
}
2018-04-12 16:10:22 +02:00
cfg . SaveTo ( config )
2018-04-12 00:46:33 +02:00
}
2018-04-02 12:17:50 +02:00
fmt . Println ( "\nPress Enter to exit" )
2018-04-18 13:29:45 +02:00
//fmt.Scanln()
2018-04-09 15:02:46 +02:00
}