Download src/gallery.ts from launch-calcium/Gallery-Copper-Typescript: direct link, hf CLI and curl.
- Browser
- Download file 6.72 kB
-
https://huggingface.co/spaces/launch-calcium/Gallery-Copper-Typescript/resolve/main/src/gallery.ts
- Command line
-
hf download hf://spaces/launch-calcium/Gallery-Copper-Typescript/src/gallery.ts
-
curl -L -o gallery.ts https://huggingface.co/spaces/launch-calcium/Gallery-Copper-Typescript/resolve/main/src/gallery.ts
6.72 kB
| import express from 'express'; | |
| import multer from 'multer'; | |
| import path from 'path'; | |
| import fs from 'fs'; | |
| import { db, getConfig } from './db'; | |
| import { processUploadedImage } from './imageService'; | |
| export const galleryRouter = express.Router(); | |
| const upload = multer({ dest: path.join(__dirname, '../uploads/tmp') }); | |
| galleryRouter.get('/', (req, res) => { | |
| const catParam = req.query.cat ? Number(req.query.cat) : 0; | |
| const page = req.query.page ? Math.max(1, Number(req.query.page)) : 1; | |
| const config = getConfig(); | |
| const perPage = Number(config.albums_per_page) || 12; | |
| const categories = db.prepare('SELECT * FROM categories WHERE parent = ? ORDER BY pos ASC, name ASC').all(catParam) as any[]; | |
| const albCountRow = db.prepare('SELECT COUNT(*) as count FROM albums WHERE category = ?').get(catParam) as any; | |
| const totalAlbums = albCountRow ? albCountRow.count : 0; | |
| const totalPages = Math.ceil(totalAlbums / perPage) || 1; | |
| const offset = (page - 1) * perPage; | |
| const albums = db.prepare(` | |
| SELECT a.*, | |
| (SELECT COUNT(*) FROM pictures p WHERE p.aid = a.aid) as pic_count, | |
| (SELECT filename FROM pictures p WHERE p.aid = a.aid ORDER BY pid DESC LIMIT 1) as thumb_filename | |
| FROM albums a | |
| WHERE a.category = ? | |
| ORDER BY a.pos ASC, a.aid DESC | |
| LIMIT ? OFFSET ? | |
| `).all(catParam, perPage, offset) as any[]; | |
| const recentPics = db.prepare('SELECT * FROM pictures ORDER BY pid DESC LIMIT 8').all() as any[]; | |
| res.render('index', { | |
| title: config.gallery_name, | |
| description: config.gallery_description, | |
| categories, | |
| albums, | |
| recentPics, | |
| currentCat: catParam, | |
| page, | |
| totalPages, | |
| user: (req.session as any).user || null | |
| }); | |
| }); | |
| galleryRouter.get('/album/:aid', (req, res) => { | |
| const aid = Number(req.params.aid); | |
| const album = db.prepare('SELECT * FROM albums WHERE aid = ?').get(aid) as any; | |
| if (!album) { | |
| return res.status(404).render('message', { title: 'Not Found', message: 'Album does not exist.', backUrl: '/' }); | |
| } | |
| db.prepare('UPDATE albums SET alb_hits = alb_hits + 1 WHERE aid = ?').run(aid); | |
| const page = req.query.page ? Math.max(1, Number(req.query.page)) : 1; | |
| const config = getConfig(); | |
| const perPage = Number(config.pics_per_page) || 12; | |
| const picCountRow = db.prepare('SELECT COUNT(*) as count FROM pictures WHERE aid = ?').get(aid) as any; | |
| const totalPics = picCountRow ? picCountRow.count : 0; | |
| const totalPages = Math.ceil(totalPics / perPage) || 1; | |
| const offset = (page - 1) * perPage; | |
| const pictures = db.prepare('SELECT * FROM pictures WHERE aid = ? ORDER BY pid DESC LIMIT ? OFFSET ?').all(aid, perPage, offset) as any[]; | |
| res.render('album', { | |
| title: album.title, | |
| album, | |
| pictures, | |
| page, | |
| totalPages, | |
| user: (req.session as any).user || null | |
| }); | |
| }); | |
| galleryRouter.get('/picture/:pid', (req, res) => { | |
| const pid = Number(req.params.pid); | |
| const picture = db.prepare('SELECT * FROM pictures WHERE pid = ?').get(pid) as any; | |
| if (!picture) { | |
| return res.status(404).render('message', { title: 'Not Found', message: 'Picture does not exist.', backUrl: '/' }); | |
| } | |
| db.prepare('UPDATE pictures SET hits = hits + 1 WHERE pid = ?').run(pid); | |
| const album = db.prepare('SELECT * FROM albums WHERE aid = ?').get(picture.aid) as any; | |
| const comments = db.prepare('SELECT * FROM comments WHERE pid = ? ORDER BY msg_id ASC').all(pid) as any[]; | |
| const prevPic = db.prepare('SELECT pid FROM pictures WHERE aid = ? AND pid < ? ORDER BY pid DESC LIMIT 1').get(picture.aid, pid) as any; | |
| const nextPic = db.prepare('SELECT pid FROM pictures WHERE aid = ? AND pid > ? ORDER BY pid ASC LIMIT 1').get(picture.aid, pid) as any; | |
| res.render('displayimage', { | |
| title: picture.title || picture.filename, | |
| picture, | |
| album, | |
| comments, | |
| prevPid: prevPic ? prevPic.pid : null, | |
| nextPid: nextPic ? nextPic.pid : null, | |
| user: (req.session as any).user || null | |
| }); | |
| }); | |
| galleryRouter.post('/picture/:pid/comment', (req, res) => { | |
| const pid = Number(req.params.pid); | |
| const { msg_author, msg_body } = req.body; | |
| const user = (req.session as any).user; | |
| const authorName = user ? user.name : (msg_author || 'Guest'); | |
| const authorId = user ? user.id : 0; | |
| if (msg_body && msg_body.trim().length > 0) { | |
| db.prepare('INSERT INTO comments (pid, msg_author, msg_body, author_id) VALUES (?, ?, ?, ?)').run(pid, authorName, msg_body.trim(), authorId); | |
| } | |
| res.redirect(`/picture/${pid}`); | |
| }); | |
| galleryRouter.post('/picture/:pid/rate', (req, res) => { | |
| const pid = Number(req.params.pid); | |
| const rating = Math.min(5, Math.max(1, Number(req.body.rating) || 0)); | |
| if (rating > 0) { | |
| const pic = db.prepare('SELECT pic_rating, votes FROM pictures WHERE pid = ?').get(pid) as any; | |
| if (pic) { | |
| const newVotes = pic.votes + 1; | |
| const newRating = Math.round(((pic.pic_rating * pic.votes) + (rating * 2000)) / newVotes); | |
| db.prepare('UPDATE pictures SET pic_rating = ?, votes = ? WHERE pid = ?').run(newRating, newVotes, pid); | |
| } | |
| } | |
| res.redirect(`/picture/${pid}`); | |
| }); | |
| galleryRouter.get('/upload', (req, res) => { | |
| const user = (req.session as any).user; | |
| if (!user) { | |
| return res.redirect('/login'); | |
| } | |
| const albums = db.prepare('SELECT * FROM albums ORDER BY title ASC').all() as any[]; | |
| res.render('upload', { title: 'Upload File', albums, user }); | |
| }); | |
| galleryRouter.post('/upload', upload.single('userfile'), async (req, res) => { | |
| const user = (req.session as any).user; | |
| if (!user) { | |
| return res.redirect('/login'); | |
| } | |
| const { aid, title, caption, keywords } = req.body; | |
| if (!req.file || !aid) { | |
| return res.render('message', { title: 'Upload Failed', message: 'Please select an image file and target album.', backUrl: '/upload' }); | |
| } | |
| try { | |
| const ext = path.extname(req.file.originalname).toLowerCase(); | |
| const uniqueFilename = `${Date.now()}_${Math.floor(Math.random() * 10000)}${ext}`; | |
| const processed = await processUploadedImage(req.file.path, uniqueFilename); | |
| fs.unlinkSync(req.file.path); | |
| db.prepare(` | |
| INSERT INTO pictures (aid, filepath, filename, filesize, pwidth, pheight, owner_id, title, caption, keywords) | |
| VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) | |
| `).run( | |
| Number(aid), | |
| processed.filepath, | |
| processed.filename, | |
| processed.filesize, | |
| processed.pwidth, | |
| processed.pheight, | |
| user.id, | |
| title || '', | |
| caption || '', | |
| keywords || '' | |
| ); | |
| res.redirect(`/album/${aid}`); | |
| } catch (err: any) { | |
| console.error('Upload Error:', err); | |
| res.render('message', { title: 'Upload Error', message: err.message || 'Failed to process uploaded file.', backUrl: '/upload' }); | |
| } | |
| }); | |