<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"time"

	"github.com/fanpei91/bencode"
	"github.com/fanpei91/godht"
	"github.com/fanpei91/metawire"
)

const (
	Dir = "torrents"
)

func home() string {
	env := "HOME"
	if runtime.GOOS == "windows" {
		env = "USERPROFILE"
	} else if runtime.GOOS == "plan9" {
		env = "home"
	}
	return os.Getenv(env)
}

type tfile struct {
	name   string
	length int64
}

func (tf *tfile) String() string {
	return fmt.Sprintf("name: %s\n, size: %d\n", tf.name, tf.length)
}

type torrent struct {
	infohashHex string
	name        string
	length      int64
	files       []*tfile
}

func (t *torrent) String() string {
	return fmt.Sprintf(
		"link: %s\nname: %s\nsize: %d\nfile: %d\n",
		fmt.Sprintf("magnet:?xt=urn:btih:%s", t.infohashHex),
		t.name,
		t.length,
		len(t.files),
	)
}

func newTorrent(meta []byte, infohashHex string) (*torrent, error) {
	dict, err := bencode.Decode(bytes.NewBuffer(meta))
	if err != nil {
		return nil, err
	}
	t := &torrent{infohashHex: infohashHex}
	if name, ok := dict["name.utf-8"].(string); ok {
		t.name = name
	} else if name, ok := dict["name"].(string); ok {
		t.name = name
	}
	if length, ok := dict["length"].(int64); ok {
		t.length = length
	}
	var total int64
	if files, ok := dict["files"].([]interface{}); ok {
		for _, file := range files {
			var filename string
			var filelength int64
			if f, ok := file.(map[string]interface{}); ok {
				if path, ok := f["path.utf-8"].([]string); ok {
					filename = strings.Join(path, "/")
				} else if path, ok := f["path"].([]string); ok {
					filename = strings.Join(path, "/")
				}
				if length, ok := f["length"].(int64); ok {
					filelength = length
					total += filelength
				}
				t.files = append(t.files, &tfile{name: filename, length: filelength})
			}
		}
	}
	if t.length == 0 {
		t.length = total
	}
	return t, nil
}

type blacklist struct {
	container    sync.Map
	expiredAfter time.Duration
}

func newBalckList(expiredAfter time.Duration) *blacklist {
	b := &blacklist{expiredAfter: expiredAfter}
	go b.sweep()
	return b
}

func (b *blacklist) in(addr *net.TCPAddr) bool {
	key := addr.String()
	v, ok := b.container.Load(key)
	if !ok {
		return false
	}<commit_msg>Fixed filename's error. Correct file list if file is only one (#63)<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"time"

	"github.com/fanpei91/bencode"
	"github.com/fanpei91/godht"
	"github.com/fanpei91/metawire"
)

const (
	Dir = "torrents"
)

func home() string {
	env := "HOME"
	if runtime.GOOS == "windows" {
		env = "USERPROFILE"
	} else if runtime.GOOS == "plan9" {
		env = "home"
	}
	return os.Getenv(env)
}

type tfile struct {
	name   string
	length int64
}

func (tf *tfile) String() string {
	return fmt.Sprintf("name: %s\n, size: %d\n", tf.name, tf.length)
}

type torrent struct {
	infohashHex string
	name        string
	length      int64
	files       []*tfile
}

func (t *torrent) String() string {
	return fmt.Sprintf(
		"link: %s\nname: %s\nsize: %d\nfile: %d\n",
		fmt.Sprintf("magnet:?xt=urn:btih:%s", t.infohashHex),
		t.name,
		t.length,
		len(t.files),
	)
}

func newTorrent(meta []byte, infohashHex string) (*torrent, error) {
	dict, err := bencode.Decode(bytes.NewBuffer(meta))
	if err != nil {
		return nil, err
	}
	t := &torrent{infohashHex: infohashHex}
	if name, ok := dict["name.utf-8"].(string); ok {
		t.name = name
	} else if name, ok := dict["name"].(string); ok {
		t.name = name
	}
	if length, ok := dict["length"].(int64); ok {
		t.length = length
	}
	var total int64
	if files, ok := dict["files"].([]interface{}); ok {
		for _, file := range files {
			var filename string
			var filelength int64
			if f, ok := file.(map[string]interface{}); ok {
				if inter, ok := f["path.utf-8"].([]interface{}); ok {
					path := make([]string, len(inter))
					for i, v := range inter {
					    path[i] = fmt.Sprint(v)
					}
					filename = strings.Join(path, "/")
				} else if inter, ok := f["path"].([]interface{}); ok {
					path := make([]string, len(inter))
					for i, v := range inter {
					    path[i] = fmt.Sprint(v)
					}
					filename = strings.Join(path, "/")
				}
				if length, ok := f["length"].(int64); ok {
					filelength = length
					total += filelength
				}
				t.files = append(t.files, &tfile{name: filename, length: filelength})
			}
		}
	}
	if t.length == 0 {
		t.length = total
	}
	if len(t.files) == 0 {
		t.files = append(t.files, &tfile{name: t.name, length: t.length})
	}
	return t, nil
}

type blacklist struct {
	container    sync.Map
	expiredAfter time.Duration
}

func newBalckList(expiredAfter time.Duration) *blacklist {
	b := &blacklist{expiredAfter: expiredAfter}
	go b.sweep()
	return b
}

func (b *blacklist) in(addr *net.TCPAddr) bool {
	key := addr.String()
	v, ok := b.container.Load(key)
	if !ok {
		return false
	}
{'fraction_non_alphanumeric': 0.17354877318970677, 'fraction_numerical': 0.009375623379214043, 'mean_word_length': 3.1748542880932558, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5058868', 'n_tokens_mistral': 2155, 'n_tokens_neox': 1974, 'n_words': 484}