blob: adfd2283d5e5da03028491dcf464654d3784b1ae [file] [log] [blame]
Akrone2161562022-12-19 17:05:39 +01001package main
2
3import (
Akron3890fcc2022-12-20 15:26:36 +01004 "encoding/csv"
Akron65503a32023-01-02 12:38:32 +01005 "encoding/json"
Akron3890fcc2022-12-20 15:26:36 +01006 "io"
Akrone2161562022-12-19 17:05:39 +01007 "log"
8 "net/http"
Akron3890fcc2022-12-20 15:26:36 +01009 "os"
Akrone2161562022-12-19 17:05:39 +010010
11 badger "github.com/dgraph-io/badger/v3"
12 "github.com/gin-gonic/gin"
Akronce286af2022-12-28 13:58:26 +010013 "github.com/joho/godotenv"
Akron65503a32023-01-02 12:38:32 +010014 "github.com/mattn/go-jsonpointer"
Akrone2161562022-12-19 17:05:39 +010015)
16
17var db *badger.DB
18
19func CheckSaleUrl(c *gin.Context) {
20
21 corpusID := c.Param("corpus_id")
22 docID := c.Param("doc_id")
23 textID := c.Param("text_id")
24
25 err := db.View(func(txn *badger.Txn) error {
26
27 item, err := txn.Get([]byte(corpusID + "/" + docID + "/" + textID))
28
29 if err != nil {
30 c.String(http.StatusNotFound, "No entry found")
Akron906a2c52022-12-21 11:35:28 +010031 return nil
Akrone2161562022-12-19 17:05:39 +010032 }
33
34 err = item.Value(func(v []byte) error {
35 c.String(http.StatusOK, string(v))
36 return nil
37 })
38
39 if err != nil {
Akronce5186d2022-12-21 11:15:50 +010040 return err
Akrone2161562022-12-19 17:05:39 +010041 }
42
43 return nil
44 })
45
46 if err != nil {
47 c.String(http.StatusNotFound, err.Error())
48 }
Akrone2161562022-12-19 17:05:39 +010049}
50
Akron6aee7fe2022-12-20 16:00:54 +010051func add(corpusID, docID, textID string, provider string, url string) error {
Akrone2161562022-12-19 17:05:39 +010052 err := db.Update(func(txn *badger.Txn) error {
Akron6aee7fe2022-12-20 16:00:54 +010053 err := txn.Set([]byte(corpusID+"/"+docID+"/"+textID), []byte(provider+","+url))
Akrone2161562022-12-19 17:05:39 +010054 return err
55 })
56 return err
57}
58
59func initDB(dir string) {
60 if db != nil {
61 return
62 }
63 var err error
64 db, err = badger.Open(badger.DefaultOptions(dir))
65 if err != nil {
66 log.Fatal(err)
67 }
68}
69
70func closeDB() {
71 db.Close()
72}
73
74func setupRouter() *gin.Engine {
75 r := gin.Default()
Akron5e1252e2022-12-19 17:57:56 +010076 r.LoadHTMLGlob("templates/*")
77
Akronce286af2022-12-28 13:58:26 +010078 korapServer := os.Getenv("KORAP_SERVER")
79 if korapServer == "" {
80 korapServer = "https://korap.ids-mannheim.de"
81 }
82
Akron65503a32023-01-02 12:38:32 +010083 var pluginManifest map[string]any
84 json.Unmarshal([]byte(`{
85 "name" : "External Provider",
86 "desc" : "Buy content from an external provider",
87 "embed" : [{
88 "panel" : "match",
89 "title" : "Full Text",
90 "classes" : ["plugin", "cart"],
91 "icon" : "\f07a",
92 "onClick" : {
93 "action" : "addWidget",
94 "template":"",
95 "permissions": [
96 "scripts",
97 "popups"
98 ]
99 }
100 }]
101 }`), &pluginManifest)
102
103 externalProvider := os.Getenv("KORAP_EXTERNAL_PROVIDER")
104 if externalProvider == "" {
105 externalProvider = "https://korap.ids-mannheim.de/plugin/external/"
106 }
107 jsonpointer.Set(pluginManifest, "/embed/0/onClick/template", externalProvider)
108
Akron79d83482023-01-02 10:53:24 +0100109 r.Use(func() gin.HandlerFunc {
110 return func(c *gin.Context) {
111 h := c.Writer.Header()
112 h.Set("Access-Control-Allow-Origin", "null")
113 h.Set("Access-Control-Allow-Credentials", "null")
114 h.Set("Vary", "Origin")
115 }
116 }(),
117 )
118
Akron60e11602023-01-02 11:16:43 +0100119 // Return widget page
Akron6aee7fe2022-12-20 16:00:54 +0100120 r.GET("/", func(c *gin.Context) {
Akron5e1252e2022-12-19 17:57:56 +0100121 c.HTML(http.StatusOK, "main.html", gin.H{
Akronce286af2022-12-28 13:58:26 +0100122 "korapServer": korapServer,
Akron5e1252e2022-12-19 17:57:56 +0100123 })
124 })
125
Akron60e11602023-01-02 11:16:43 +0100126 // Return provider information
Akronce5186d2022-12-21 11:15:50 +0100127 r.HEAD("/:corpus_id/:doc_id/:text_id", CheckSaleUrl)
Akrone2161562022-12-19 17:05:39 +0100128 r.GET("/:corpus_id/:doc_id/:text_id", CheckSaleUrl)
Akron60e11602023-01-02 11:16:43 +0100129
130 // Return plugin manifest
Akron65503a32023-01-02 12:38:32 +0100131 r.GET("/plugin.json", func(c *gin.Context) {
132 c.JSON(200, pluginManifest)
133 })
134
Akrone2161562022-12-19 17:05:39 +0100135 return r
136}
137
138func main() {
Akron3c58d0d2023-01-02 13:35:41 +0100139 if godotenv.Load() != nil {
140 log.Println(".env file not loaded.")
141 }
Akronce286af2022-12-28 13:58:26 +0100142
Akrone2161562022-12-19 17:05:39 +0100143 initDB("db")
Akron3890fcc2022-12-20 15:26:36 +0100144 defer closeDB()
145
146 // Index csv file
147 if len(os.Args) > 1 {
148
149 file, err := os.Open(os.Args[1])
150 if err != nil {
151 log.Fatal(err)
152 }
153 r := csv.NewReader(file)
154
155 txn := db.NewTransaction(true)
156
157 i := 0
158
159 for {
160 record, err := r.Read()
161 if err == io.EOF {
162 break
163 }
164 if err != nil {
165 log.Fatal(err)
166 }
167
168 if err := txn.Set([]byte(record[0]), []byte(record[1]+","+record[2])); err == badger.ErrTxnTooBig {
169 log.Println("Commit", record[0], "after", i, "inserts")
170 i = 0
171 err = txn.Commit()
172 if err != nil {
173 log.Fatal("Unable to commit")
174 }
175 txn = db.NewTransaction(true)
176 _ = txn.Set([]byte(record[0]), []byte(record[1]+","+record[2]))
177 }
178 i++
179 }
180 err = txn.Commit()
181
182 if err != nil {
183 log.Fatal("Unable to commit")
184 }
185
186 return
187 }
Akrone2161562022-12-19 17:05:39 +0100188 r := setupRouter()
Akronce286af2022-12-28 13:58:26 +0100189
Akron3c58d0d2023-01-02 13:35:41 +0100190 port := os.Getenv("KORAP_EXTERNAL_PROVIDER_PORT")
Akronce286af2022-12-28 13:58:26 +0100191 if port == "" {
192 port = "5722"
193 }
194
195 log.Fatal(http.ListenAndServe(":"+port, r))
Akrone2161562022-12-19 17:05:39 +0100196}