From 45c3930c95a2d6c47a7888ef5a58c85414650add Mon Sep 17 00:00:00 2001 From: Flaze <51487578+flazepe@users.noreply.github.com> Date: Sun, 1 May 2022 02:09:32 +0800 Subject: [PATCH 1/6] feat: render images as pixelated This removes the smoothing filter and makes sure the pixels stay the same no matter how much you zoom in. --- utils/themify.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/themify.js b/utils/themify.js index 2db9886..5487a83 100644 --- a/utils/themify.js +++ b/utils/themify.js @@ -53,7 +53,7 @@ function getCountImage({ count, theme='moebooru', length=7 }) { }, '') return ` - + Moe Count ${parts} @@ -64,4 +64,4 @@ function getCountImage({ count, theme='moebooru', length=7 }) { module.exports = { getCountImage -} \ No newline at end of file +} From c3f18f8b34bd8403a040a263bc8354bc7a9b4eae Mon Sep 17 00:00:00 2001 From: journey-ad Date: Mon, 6 Mar 2023 18:57:41 +0800 Subject: [PATCH 2/6] perf: Delayed writing to database - Implement delayed writing feature to database for improved performance and reduced write frequency - Update docs --- .gitignore | 1 + Readme.md | 22 +++++++++---------- config.yml | 2 +- db/mongodb.js | 18 +++++++++++++++- db/sqlite.js | 57 ++++++++++++++++++++++++++++--------------------- index.js | 45 +++++++++++++++++++++++++++++++++----- package.json | 6 +++--- views/index.pug | 4 ++-- 8 files changed, 108 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index cb9c106..b329f95 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +count.db /.history # dependencies diff --git a/Readme.md b/Readme.md index 1164e8f..a521391 100644 --- a/Readme.md +++ b/Readme.md @@ -1,8 +1,8 @@ -# Moe-counter +# Moe-Counter 多种风格可选的萌萌计数器 -![Moe-counter](https://count.getloli.com/get/@Moe-counter.github) +![Moe-Counter](https://count.getloli.com/get/@Moe-counter.github)
More theme @@ -26,17 +26,17 @@ ### Install -#### Run on Repl.it +#### Run on Replit -- Open the url [https://repl.it/@journeyad/Moe-counter](https://repl.it/@journeyad/Moe-counter) +- Open the url [https://replit.com/@journeyad/Moe-Counter](https://replit.com/@journeyad/Moe-Counter) - Just hit the **Fork** button - And hit the **Run** button #### Deploying on your own server ```shell -$ git clone https://github.com/journey-ad/Moe-counter.git -$ cd Moe-counter +$ git clone https://github.com/journey-ad/Moe-Counter.git +$ cd Moe-Counter $ yarn install $ yarn start @@ -51,7 +51,7 @@ app: port: 3000 db: - type: mongodb # sqlite or mongodb + type: sqlite # sqlite or mongodb ``` If you use mongodb, you need to specify the environment variable `DB_URL` @@ -61,7 +61,7 @@ If you use mongodb, you need to specify the environment variable `DB_URL` export DB_URL=mongodb+srv://account:passwd@***.***.***.mongodb.net/db_count ``` -repl.it can use `.env` file, [documentation](https://docs.repl.it/repls/secret-keys) +replit can use Secrets, [documentation](https://docs.replit.com/programming-ide/storing-sensitive-information-environment-variables) ``` DB_URL="mongodb+srv://account:passwd@***.***.***.mongodb.net/db_count" @@ -69,8 +69,8 @@ DB_URL="mongodb+srv://account:passwd@***.***.***.mongodb.net/db_count" ## Credits -* [repl.it](https://repl.it/) -* [A-SOUL](https://www.asoulworld.com/) (非官方导航站) +* [replit](https://replit.com/) +* [A-SOUL_Official](https://space.bilibili.com/703007996) * [moebooru](https://github.com/moebooru/moebooru) * rule34.xxx NSFW * gelbooru.com NSFW @@ -78,4 +78,4 @@ DB_URL="mongodb+srv://account:passwd@***.***.***.mongodb.net/db_count" ## License -[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fjourney-ad%2FMoe-counter.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fjourney-ad%2FMoe-counter?ref=badge_large) +[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fjourney-ad%2FMoe-Counter.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fjourney-ad%2FMoe-Counter?ref=badge_large) diff --git a/config.yml b/config.yml index f63ed72..6e6bc78 100644 --- a/config.yml +++ b/config.yml @@ -2,4 +2,4 @@ app: port: 3000 db: - type: mongodb # sqlite or mongodb \ No newline at end of file + type: sqlite # sqlite or mongodb diff --git a/db/mongodb.js b/db/mongodb.js index 57f1b72..4119c7a 100644 --- a/db/mongodb.js +++ b/db/mongodb.js @@ -32,8 +32,24 @@ function setNum(name, num) { .exec() } +function setNumMulti(counters) { + const bulkOps = counters.map(obj => { + const { name, num } = obj + return { + updateOne: { + filter: { name }, + update: { name, num }, + upsert: true + } + } + }) + + return Count.bulkWrite(bulkOps, { ordered : false }) +} + module.exports = { getNum, getAll, - setNum + setNum, + setNumMulti } diff --git a/db/sqlite.js b/db/sqlite.js index 0912101..4b09dd1 100644 --- a/db/sqlite.js +++ b/db/sqlite.js @@ -1,11 +1,11 @@ 'use strict' const path = require('path') -const sqlite3 = require('sqlite3') +const Database = require('better-sqlite3') -const db = new sqlite3.Database(path.resolve(__dirname, '../count.db')) +const db = new Database(path.resolve(__dirname, '../count.db')) -db.run(`CREATE TABLE IF NOT EXISTS tb_count ( +db.exec(`CREATE TABLE IF NOT EXISTS tb_count ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, @@ -17,44 +17,53 @@ db.run(`CREATE TABLE IF NOT EXISTS tb_count ( function getNum(name) { return new Promise((resolve, reject) => { - db.get('SELECT `name`, `num` from tb_count WHERE `name` = ?', name, (err, row) => { - if (err) reject(err) - - resolve(row || { name, num: 0 }) - }) + const stmt = db.prepare('SELECT `name`, `num` from tb_count WHERE `name` = ?') + const row = stmt.get(name) + resolve(row || { name, num: 0 }) }) } function getAll(name) { return new Promise((resolve, reject) => { - db.get('SELECT * from tb_count', (err, row) => { - if (err) reject(err) - - resolve(row) - }) + const stmt = db.prepare('SELECT * from tb_count') + const rows = stmt.all() + resolve(rows) }) } function setNum(name, num) { return new Promise((resolve, reject) => { - db.run(`INSERT INTO tb_count(\`name\`, \`num\`) + db.exec(`INSERT INTO tb_count(\`name\`, \`num\`) VALUES($name, $num) ON CONFLICT(name) DO UPDATE SET \`num\` = $num;` - , { - $name: name, - $num: num - } - , (err, row) => { - if (err) reject(err) + , + { $name: name, $num: num } + ) - resolve(row) - }) + resolve() + }) +} + +function setNumMulti(counters) { + return new Promise((resolve, reject) => { + const stmt = db.prepare(`INSERT INTO tb_count(\`name\`, \`num\`) + VALUES($name, $num) + ON CONFLICT(name) DO + UPDATE SET \`num\` = $num;`) + + const setMany = db.transaction((counters) => { + for (const counter of counters) stmt.run(counter) + }) + + setMany(counters) + resolve() }) } module.exports = { getNum, getAll, - setNum -} \ No newline at end of file + setNum, + setNumMulti +} diff --git a/index.js b/index.js index 88e6828..641348b 100644 --- a/index.js +++ b/index.js @@ -45,7 +45,7 @@ app.get('/get/@:name', async (req, res) => { const renderSvg = themify.getCountImage({ count: data.num, theme, length }) res.send(renderSvg) - console.log(data, `theme: ${theme}`) + console.log(data, `theme: ${theme}`, `ref: ${req.get('Referrer') || null}`, `ua: ${req.get('User-Agent') || null}`) }) // JSON record @@ -70,16 +70,51 @@ const listener = app.listen(config.app.port || 3000, () => { console.log('Your app is listening on port ' + listener.address().port) }) +let __cache_counter = {}, shouldPush = false + +setInterval(() => { + shouldPush = true +}, 1000 * 60); + +async function pushDB() { + if (!shouldPush) return + + try { + shouldPush = false + if (Object.keys(__cache_counter).length === 0) return + + console.log("pushDB", __cache_counter) + + const counters = Object.keys(__cache_counter).map(key => { + return { + name: key, + num: __cache_counter[key] + } + }) + + await db.setNumMulti(counters) + __cache_counter = {} + } catch (error) { + console.log("pushDB is error: ", error) + } +} + async function getCountByName(name) { const defaultCount = { name, num: 0 } if (name === 'demo') return { name, num: '0123456789' } try { - const counter = await db.getNum(name) || defaultCount - const num = counter.num + 1 - db.setNum(counter.name, num) - return counter + if (!(name in __cache_counter)) { + const counter = await db.getNum(name) || defaultCount + __cache_counter[name] = counter.num + 1 + } else { + __cache_counter[name]++ + } + + pushDB() + + return { name, num: __cache_counter[name] } } catch (error) { console.log("get count by name is error: ", error) diff --git a/package.json b/package.json index baf9850..df1b7d6 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "kawaii-counter", + "name": "moe-counter", "version": "1.0.0", "description": "", "main": "index.js", @@ -11,13 +11,13 @@ "author": "journey-ad", "license": "MIT", "dependencies": { + "better-sqlite3": "^8.1.0", "compression": "^1.7.4", "config-yml": "^0.10.3", "express": "^4.17.1", "image-size": "^0.8.3", "mime-types": "^2.1.27", "mongoose": "^5.9.28", - "pug": "^3.0.0", - "sqlite3": "^5.0.0" + "pug": "^3.0.0" } } diff --git a/views/index.pug b/views/index.pug index fa2dadf..4f681d3 100644 --- a/views/index.pug +++ b/views/index.pug @@ -62,7 +62,7 @@ html li a(href='https://repl.it/', target='_blank', rel='nofollow') repl.it li - a(href='https://www.asoulworld.com/', target='_blank', title='A-SOUL导航站(非官方)') A-SOUL + a(href='https://space.bilibili.com/703007996', target='_blank', title='A-SOUL_Official') A-SOUL li a(href='https://github.com/moebooru/moebooru', target='_blank', rel='nofollow') moebooru li @@ -109,4 +109,4 @@ html iframe(src="https://chat.getloli.com/room/@Moe-counter?title=%E8%90%8C%E8%90%8C%E8%AE%A1%E6%95%B0%E5%99%A8%E7%9A%84%E7%95%99%E8%A8%80%E6%9D%BF", scrolling="no", frameborder="0", height="70%", width="26%", style="position: fixed;top: 2%;right: 5%;") p.copy - a(href='https://github.com/journey-ad/Moe-counter', target='_blank', onclick='_evt_push("click", "normal", "go_github")') source code \ No newline at end of file + a(href='https://github.com/journey-ad/Moe-Counter', target='_blank', onclick='_evt_push("click", "normal", "go_github")') source code \ No newline at end of file From 65097d982dd1ddca22de24473926656d988ccfaa Mon Sep 17 00:00:00 2001 From: eggplants Date: Thu, 9 Mar 2023 15:34:29 +0900 Subject: [PATCH 3/6] fix: typo --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index a521391..9cd1fc3 100644 --- a/Readme.md +++ b/Readme.md @@ -42,7 +42,7 @@ $ yarn install $ yarn start ``` -### Confignation +### Configuration `config.yml` From a3eb1409c4f40b01c7189eba5ee9137da553d608 Mon Sep 17 00:00:00 2001 From: HChenZi Date: Tue, 4 Apr 2023 10:10:55 +0800 Subject: [PATCH 4/6] feat: add docker deploy --- Dockerfile | 11 +++++++++++ docker-compose.yml | 6 ++++++ 2 files changed, 17 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..22dae09 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM node:14 + +WORKDIR /app + +COPY . . + +RUN yarn install + +EXPOSE 3000 + +CMD ["yarn", "start"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7d16b1a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,6 @@ +version: '3' +services: + moe-counter: + build: . + ports: + - "3000:3000" From 5d5045de54b193110d58d63554ce7da6feffca30 Mon Sep 17 00:00:00 2001 From: HChenZi Date: Tue, 4 Apr 2023 12:22:37 +0800 Subject: [PATCH 5/6] feat: Get url from req for index page --- index.js | 3 ++- views/index.pug | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/index.js b/index.js index 641348b..72c41e6 100644 --- a/index.js +++ b/index.js @@ -17,7 +17,8 @@ app.use(compression()) app.set('view engine', 'pug') app.get('/', (req, res) => { - res.render('index') + const url = req.protocol+'://'+req.get('host') + res.render('index', { url }) }); // get the image diff --git a/views/index.pug b/views/index.pug index 4f681d3..b77784a 100644 --- a/views/index.pug +++ b/views/index.pug @@ -25,16 +25,16 @@ html h3 How to use: h5 SVG address - code https://count.getloli.com/get/@:name + code #{url}/get/@:name h5 Img tag - code <img src="https://count.getloli.com/get/@:name" alt=":name" /> + code <img src="#{url}/get/@:name" alt=":name" /> h5 Markdown - code ![:name](https://count.getloli.com/get/@:name) + code ![:name](#{url}/get/@:name) h3 eg: -
Moe Count! + Moe Count! i Data can access by anyone, please | DO NOT @@ -43,19 +43,19 @@ html details summary(style='display: inline-block;', onclick='_evt_push("click", "normal", "more_theme")') h3(style='display: inline-block; cursor: pointer;') More theme - p(style='margin: 0;') Just use the query parameters theme, like this: https://count.getloli.com/get/@:name?theme=moebooru + p(style='margin: 0;') Just use the query parameters theme, like this: #{url}/get/@:name?theme=moebooru h5 asoul - img(src='https://count.getloli.com/get/@demo?theme=asoul', alt='A-SOUL') + img(src='#{url}/get/@demo?theme=asoul', alt='A-SOUL') h5 moebooru - img(src='https://count.getloli.com/get/@demo?theme=moebooru', alt='Moebooru') + img(src='#{url}/get/@demo?theme=moebooru', alt='Moebooru') h5 moebooru-h - img(src='https://count.getloli.com/get/@demo?theme=moebooru-h', alt='Moebooru-Hentai') + img(src='#{url}/get/@demo?theme=moebooru-h', alt='Moebooru-Hentai') h5 rule34 - img(src='https://count.getloli.com/get/@demo?theme=rule34', alt='Rule34') + img(src='#{url}/get/@demo?theme=rule34', alt='Rule34') h5 gelbooru - img(src='https://count.getloli.com/get/@demo?theme=gelbooru', alt='Gelbooru') + img(src='#{url}/get/@demo?theme=gelbooru', alt='Gelbooru') h5 gelbooru-h - img(src='https://count.getloli.com/get/@demo?theme=gelbooru-h', alt='Gelbooru-Hentai') + img(src='#{url}/get/@demo?theme=gelbooru-h', alt='Gelbooru-Hentai') h3 Credits ul @@ -76,7 +76,7 @@ html h3 Tool .tool - code https://count.getloli.com/get/@ + code #{url}/get/@ input#name(type='text', placeholder=':name', style='display: inline-block; width: 80px; height: 1.4em; line-height: 1.4em; margin: 0 4px; vertical-align: middle;') code ?theme= select#theme(style='display: inline-block; height: 1.6em; line-height: 1.6em; font-size: 14px; margin: 0 4px; padding: 0 4px; vertical-align: middle;') @@ -103,10 +103,10 @@ html return } - img.src = 'https://count.getloli.com/get/@' + text + '?theme=' + theme + img.src = '#{url}/get/@' + text + '?theme=' + theme }) iframe(src="https://chat.getloli.com/room/@Moe-counter?title=%E8%90%8C%E8%90%8C%E8%AE%A1%E6%95%B0%E5%99%A8%E7%9A%84%E7%95%99%E8%A8%80%E6%9D%BF", scrolling="no", frameborder="0", height="70%", width="26%", style="position: fixed;top: 2%;right: 5%;") p.copy - a(href='https://github.com/journey-ad/Moe-Counter', target='_blank', onclick='_evt_push("click", "normal", "go_github")') source code \ No newline at end of file + a(href='https://github.com/journey-ad/Moe-Counter', target='_blank', onclick='_evt_push("click", "normal", "go_github")') source code From 8e3a196dc36b1e5223d8bffead951d65538b8775 Mon Sep 17 00:00:00 2001 From: journey-ad Date: Tue, 4 Apr 2023 15:01:50 +0800 Subject: [PATCH 6/6] perf: Use more precise variable naming and support configuration. --- Readme.md | 1 + config.yml | 1 + index.js | 4 ++-- views/index.pug | 26 +++++++++++++------------- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Readme.md b/Readme.md index 9cd1fc3..d5bfd2d 100644 --- a/Readme.md +++ b/Readme.md @@ -48,6 +48,7 @@ $ yarn start ```yaml app: + # site: https://count.getloli.com # your website port: 3000 db: diff --git a/config.yml b/config.yml index 6e6bc78..a5070f3 100644 --- a/config.yml +++ b/config.yml @@ -1,4 +1,5 @@ app: + # site: https://count.getloli.com # your website port: 3000 db: diff --git a/index.js b/index.js index 72c41e6..77237b8 100644 --- a/index.js +++ b/index.js @@ -17,8 +17,8 @@ app.use(compression()) app.set('view engine', 'pug') app.get('/', (req, res) => { - const url = req.protocol+'://'+req.get('host') - res.render('index', { url }) + const site = config.app.site || `${req.protocol}://${req.get('host')}` + res.render('index', { site }) }); // get the image diff --git a/views/index.pug b/views/index.pug index b77784a..a144569 100644 --- a/views/index.pug +++ b/views/index.pug @@ -25,16 +25,16 @@ html h3 How to use: h5 SVG address - code #{url}/get/@:name + code #{site}/get/@:name h5 Img tag - code <img src="#{url}/get/@:name" alt=":name" /> + code <img src="#{site}/get/@:name" alt=":name" /> h5 Markdown - code ![:name](#{url}/get/@:name) + code ![:name](#{site}/get/@:name) h3 eg: - Moe Count! + Moe Count! i Data can access by anyone, please | DO NOT @@ -43,19 +43,19 @@ html details summary(style='display: inline-block;', onclick='_evt_push("click", "normal", "more_theme")') h3(style='display: inline-block; cursor: pointer;') More theme - p(style='margin: 0;') Just use the query parameters theme, like this: #{url}/get/@:name?theme=moebooru + p(style='margin: 0;') Just use the query parameters theme, like this: #{site}/get/@:name?theme=moebooru h5 asoul - img(src='#{url}/get/@demo?theme=asoul', alt='A-SOUL') + img(src='#{site}/get/@demo?theme=asoul', alt='A-SOUL') h5 moebooru - img(src='#{url}/get/@demo?theme=moebooru', alt='Moebooru') + img(src='#{site}/get/@demo?theme=moebooru', alt='Moebooru') h5 moebooru-h - img(src='#{url}/get/@demo?theme=moebooru-h', alt='Moebooru-Hentai') + img(src='#{site}/get/@demo?theme=moebooru-h', alt='Moebooru-Hentai') h5 rule34 - img(src='#{url}/get/@demo?theme=rule34', alt='Rule34') + img(src='#{site}/get/@demo?theme=rule34', alt='Rule34') h5 gelbooru - img(src='#{url}/get/@demo?theme=gelbooru', alt='Gelbooru') + img(src='#{site}/get/@demo?theme=gelbooru', alt='Gelbooru') h5 gelbooru-h - img(src='#{url}/get/@demo?theme=gelbooru-h', alt='Gelbooru-Hentai') + img(src='#{site}/get/@demo?theme=gelbooru-h', alt='Gelbooru-Hentai') h3 Credits ul @@ -76,7 +76,7 @@ html h3 Tool .tool - code #{url}/get/@ + code #{site}/get/@ input#name(type='text', placeholder=':name', style='display: inline-block; width: 80px; height: 1.4em; line-height: 1.4em; margin: 0 4px; vertical-align: middle;') code ?theme= select#theme(style='display: inline-block; height: 1.6em; line-height: 1.6em; font-size: 14px; margin: 0 4px; padding: 0 4px; vertical-align: middle;') @@ -103,7 +103,7 @@ html return } - img.src = '#{url}/get/@' + text + '?theme=' + theme + img.src = '#{site}/get/@' + text + '?theme=' + theme }) iframe(src="https://chat.getloli.com/room/@Moe-counter?title=%E8%90%8C%E8%90%8C%E8%AE%A1%E6%95%B0%E5%99%A8%E7%9A%84%E7%95%99%E8%A8%80%E6%9D%BF", scrolling="no", frameborder="0", height="70%", width="26%", style="position: fixed;top: 2%;right: 5%;")