main
js 49 lines 2.04 KB
Raw
1 // other plugins can use ctx.state.download_counter_ignore to mark downloads that shouldn't be counted
2
3 exports.description = "Counts downloads for each file, and displays the total in the list or file menu"
4 exports.version = 6.4 // removed legacy code; fixed wrong key for files with % in the name
5 exports.apiRequired = 8.89 // openDb
6
7 exports.config = {
8 where: { frontend: true, label: "Where to display counter", type: 'select', defaultValue: 'menu',
9 options: ['list', { value: 'menu', label: "file menu" }],
10 },
11 archives: { defaultValue: true, type: 'boolean', label: "Count files in zip/archives" },
12 }
13 exports.configDialog = {
14 sx: { maxWidth: '20em' },
15 }
16
17 exports.init = async api => {
18 const db = await api.openDb('counters.kv', { defaultPutDelay: 5_000, maxPutDelay: 30_000 })
19 return {
20 frontend_js: 'main.js',
21 frontend_css: 'style.css',
22 middleware: ctx => () => { // callback = execute after other middlewares are done
23 if (ctx.status >= 300 || ctx.state.download_counter_ignore || ctx.state.considerAsGui || ctx.state.includesLastByte === false) return
24 if (!(ctx.state.vfsNode || api.getConfig('archives') && ctx.state.archive)) return
25 ctx.state.completed.then(() => {
26 const key = uri2key(ctx.path)
27 const entries = ctx.state.vfsNode ? [key]
28 : ctx.state.originalStream?.getArchiveEntries?.().filter(x => x.at(-1) !== '/').map(x => key + path2key(x))
29 if (!entries) return
30 for (const k of entries)
31 db.put(k, db.getSync(k) + 1 || 1)
32 })
33 },
34 onDirEntry({ entry, listUri }) {
35 const k = uri2key(listUri) + path2key(entry.n)
36 const n = db.getSync(k)
37 if (n)
38 entry.hits = n
39 }
40 }
41
42 function uri2key(uri) { // normalize uri to avoid having different keys for the same file
43 return path2key(api.misc.pathDecode(uri))
44 }
45
46 function path2key(path) {
47 return path.toLowerCase()
48 }
49 }