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) error {
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 err
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 err
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 err
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 err
67 }
68 }
69 return nil
70}
71
72func GetVideoDB(videoId string) (*Video, error) {
73 db := getDb("ro")
74 defer db.Close()
75
76 getVideo, err := db.Prepare(getVideoQuery)
77 if err != nil {
78 logger.Error("Could not get video: ", err)
79 return nil, err
80 }
81 defer getVideo.Close()
82
83 v := &Video{}
84 err = getVideo.QueryRow(videoId).Scan(&v.VideoId, &v.Title, &v.Description, &v.Uploader, &v.Duration, &v.Timestamp, &v.Expire)
85 if err != nil {
86 logger.Debug("Could not get video:", err)
87 return nil, err
88 }
89
90 if v.Timestamp.After(v.Expire) {
91 logger.Info("Video has expired.")
92 return nil, fmt.Errorf("expired")
93 }
94
95 getFormat, err := db.Prepare(getFormatQuery)
96 if err != nil {
97 logger.Error("Could not get format: ", err)
98 return nil, err
99 }
100 defer getFormat.Close()
101
102 response, err := getFormat.Query(videoId)
103 if err != nil {
104 logger.Error("Could not get formats: ", err)
105 return nil, err
106 }
107 defer response.Close()
108
109 for response.Next() {
110 f := Format{}
111 err := response.Scan(&f.VideoId, &f.Name, &f.Height, &f.Width, &f.Url)
112 if err != nil {
113 logger.Error("Could not get formats: ", err)
114 return nil, err
115 }
116 v.Formats = append(v.Formats, f)
117 }
118
119 return v, nil
120}
121
122func ClearDB() {
123 db := getDb("rw")
124 defer db.Close()
125
126 stmt, err := db.Prepare(clearQuery)
127 if err != nil {
128 logger.Error("Could not clear DB:", err)
129 return
130 }
131 defer stmt.Close()
132
133 _, err = stmt.Exec()
134 if err != nil {
135 logger.Error("Could not clear DB:", err)
136 return
137 }
138}