invidious/cache.go (view raw)
1package invidious
2
3import (
4 "database/sql"
5 "fmt"
6
7 _ "github.com/mattn/go-sqlite3"
8)
9
10const dbConnectionString = "file:cache.sqlite?cache=shared&mode="
11
12func getDb(mode string) *sql.DB {
13 db, err := sql.Open("sqlite3", dbConnectionString+mode)
14 if err != nil {
15 logger.Error("Could not open DB:", err)
16 return nil
17 }
18 db.SetMaxOpenConns(1)
19 return db
20}
21
22func InitDB() {
23 db := getDb("rwc")
24 defer db.Close()
25
26 _, err := db.Exec(createQueryVideos)
27 if err != nil {
28 logger.Errorf("%q: %s\n", err, createQueryVideos)
29 return
30 }
31 _, err = db.Exec(createQueryFormats)
32 if err != nil {
33 logger.Errorf("%q: %s\n", err, createQueryFormats)
34 return
35 }
36}
37
38func CacheVideoDB(v Video) {
39 db := getDb("rw")
40 defer db.Close()
41
42 cacheVideo, err := db.Prepare(cacheVideoQuery)
43 if err != nil {
44 logger.Error("Could not cache video:", err)
45 return
46 }
47 defer cacheVideo.Close()
48
49 _, err = cacheVideo.Exec(v.VideoId, v.Title, v.Description, v.Uploader, v.Duration, v.Expire)
50 if err != nil {
51 logger.Error("Could not cache video:", err)
52 return
53 }
54
55 for _, f := range v.Formats {
56 cacheFormat, err := db.Prepare(cacheFormatQuery)
57 if err != nil {
58 logger.Error("Could not cache format:", err)
59 return
60 }
61 defer cacheVideo.Close()
62
63 _, err = cacheFormat.Exec(v.VideoId, f.Name, f.Height, f.Width, f.Url)
64 if err != nil {
65 logger.Error("Could not cache format:", err)
66 return
67 }
68 }
69}
70
71func GetVideoDB(videoId string) (*Video, error) {
72 db := getDb("ro")
73 defer db.Close()
74
75 getVideo, err := db.Prepare(getVideoQuery)
76 if err != nil {
77 logger.Error("Could not get video:", err)
78 return nil, err
79 }
80 defer getVideo.Close()
81
82 v := &Video{}
83 err = getVideo.QueryRow(videoId).Scan(&v.VideoId, &v.Title, &v.Description, &v.Uploader, &v.Duration, &v.Timestamp, &v.Expire)
84 if err != nil {
85 logger.Debug("Could not get video:", err)
86 return nil, err
87 }
88
89 if v.Timestamp.After(v.Expire) {
90 logger.Info("Video has expired.")
91 return nil, fmt.Errorf("expired")
92 }
93
94 getFormat, err := db.Prepare(getFormatQuery)
95 if err != nil {
96 logger.Error("Could not get format:", err)
97 return nil, err
98 }
99 defer getFormat.Close()
100
101 response, err := getFormat.Query(videoId)
102 if err != nil {
103 logger.Error("Could not get formats:", err)
104 return nil, err
105 }
106 defer response.Close()
107
108 for response.Next() {
109 f := Format{}
110 err := response.Scan(&f.VideoId, &f.Name, &f.Height, &f.Width, &f.Url)
111 if err != nil {
112 logger.Error("Could not get formats:", err)
113 return nil, err
114 }
115 v.Formats = append(v.Formats, f)
116 }
117
118 return v, nil
119}
120
121func ClearDB() {
122 db := getDb("rw")
123 defer db.Close()
124
125 stmt, err := db.Prepare(clearQuery)
126 if err != nil {
127 logger.Error("Could not clear DB:", err)
128 return
129 }
130 defer stmt.Close()
131
132 _, err = stmt.Exec()
133 if err != nil {
134 logger.Error("Could not clear DB:", err)
135 return
136 }
137}