forked from boramalper/magnetico
/
interface.go
128 lines (109 loc) · 3.17 KB
/
interface.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package persistence
import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"net/url"
)
type Database interface {
Engine() databaseEngine
DoesTorrentExist(infoHash []byte) (bool, error)
AddNewTorrent(infoHash []byte, name string, files []File) error
Close() error
// GetNumberOfTorrents returns the number of torrents saved in the database. Might be an
// approximation.
GetNumberOfTorrents() (uint, error)
// QueryTorrents returns @pageSize amount of torrents,
// * that are discovered before @discoveredOnBefore
// * that match the @query if it's not empty, else all torrents
// * ordered by the @orderBy in ascending order if @ascending is true, else in descending order
// after skipping (@page * @pageSize) torrents that also fits the criteria above.
//
// On error, returns (nil, error), otherwise a non-nil slice of TorrentMetadata and nil.
QueryTorrents(
query string,
epoch int64,
orderBy OrderingCriteria,
ascending bool,
limit uint,
lastOrderedValue *float64,
lastID *uint64,
) ([]TorrentMetadata, error)
// GetTorrents returns the TorrentExtMetadata for the torrent of the given InfoHash. Will return
// nil, nil if the torrent does not exist in the database.
GetTorrent(infoHash []byte) (*TorrentMetadata, error)
GetFiles(infoHash []byte) ([]File, error)
GetStatistics(from string, n uint) (*Statistics, error)
}
type OrderingCriteria uint8
const (
ByRelevance OrderingCriteria = iota
ByTotalSize
ByDiscoveredOn
ByNFiles
ByNSeeders
ByNLeechers
ByUpdatedOn
)
// TODO: search `swtich (orderBy)` and see if all cases are covered all the time
type databaseEngine uint8
const (
Sqlite3 databaseEngine = iota + 1
Postgres
Cockroach
)
type Statistics struct {
NDiscovered map[string]uint64 `json:"nDiscovered"`
NFiles map[string]uint64 `json:"nFiles"`
TotalSize map[string]uint64 `json:"totalSize"`
}
type File struct {
Size int64 `json:"size"`
Path string `json:"path"`
}
type TorrentMetadata struct {
ID uint64 `json:"id"`
InfoHash []byte `json:"infoHash"` // marshalled differently
Name string `json:"name"`
Size uint64 `json:"size"`
DiscoveredOn int64 `json:"discoveredOn"`
NFiles uint `json:"nFiles"`
Relevance float64 `json:"relevance"`
}
type SimpleTorrentSummary struct {
InfoHash string `json:"infoHash"`
Name string `json:"name"`
Files []File `json:"files"`
}
func (tm *TorrentMetadata) MarshalJSON() ([]byte, error) {
type Alias TorrentMetadata
return json.Marshal(&struct {
InfoHash string `json:"infoHash"`
*Alias
}{
InfoHash: hex.EncodeToString(tm.InfoHash),
Alias: (*Alias)(tm),
})
}
func MakeDatabase(rawURL string) (Database, error) {
url_, err := url.Parse(rawURL)
if err != nil {
return nil, errors.New("url.Parse " + err.Error())
}
switch url_.Scheme {
case "sqlite", "sqlite3":
return makeSqlite3Database(url_)
case "postgres", "cockroach":
return makePostgresDatabase(url_)
default:
return nil, fmt.Errorf("unknown URI scheme: `%s`", url_.Scheme)
}
}
func NewStatistics() (s *Statistics) {
s = new(Statistics)
s.NDiscovered = make(map[string]uint64)
s.NFiles = make(map[string]uint64)
s.TotalSize = make(map[string]uint64)
return
}