| | const express = require('express') |
| | const app = express() |
| | const path = require('path') |
| | const fg = require('fast-glob') |
| |
|
| | const port = 3000 |
| | const imgExt = 'jpeg' |
| |
|
| | app.use(express.urlencoded({ extended: true })) |
| |
|
| | app.use(function(req, res, next) { |
| | res.header("Access-Control-Allow-Origin", "*") |
| | res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept") |
| | next() |
| | }) |
| |
|
| | app.use('/lora', express.static('networks/lora')) |
| | app.use('/styles', express.static('networks/styles')) |
| | app.use('/checkpoints', express.static('networks/checkpoints')) |
| | app.use('/embeddings', express.static('networks/embeddings')) |
| | app.use('/hypernets', express.static('networks/hypernets')) |
| | app.use('/poses', express.static('networks/poses')) |
| | app.use('/gallery', express.static('networks/gallery')) |
| |
|
| | |
| | app.get('/images', (req, res) => { |
| |
|
| | const searchTerm = req.query.search || null |
| | const searchType = req.query.type || 'lora' |
| | let images = [] |
| |
|
| | if (searchType == "styles") { |
| | |
| | |
| |
|
| | const fs = require('fs') |
| | const {parse} = require ('csv-parse') |
| | const pattern = searchTerm ? `.*?${searchTerm}.*` : '.*' |
| | const re = new RegExp(pattern, 'gi') |
| |
|
| | let index = -1 |
| |
|
| | fs.createReadStream('networks/styles.csv') |
| | .pipe(parse({ delimiter: ',', columns: true, trim: true })) |
| | .on('data', (row) => { |
| | if (row.name.match(re) || row.prompt.match(re)) { |
| | let imageData = { |
| | filename: row.name + "." + imgExt, |
| | path: "styles/", |
| | name: row.name, |
| | author: null, |
| | tags: null, |
| | keywords: null, |
| | weight: null, |
| | prompt: row.prompt, |
| | mtimeMs: index++, |
| | mtime: null, |
| | } |
| | images.push(imageData); |
| | } |
| | }) |
| | .on('end', () => { |
| | res.json(images) |
| | }); |
| |
|
| | } else { |
| | |
| | |
| |
|
| | if (searchType == "gallery") { |
| | |
| |
|
| | let pattern = '' |
| | let extraPattern = '' |
| | let _onlyDirectories = true |
| |
|
| | if (searchTerm) { |
| | if (searchTerm.split(">").length > 1) { |
| | pattern = searchTerm.split(">")[0] ? `*${searchTerm.split(">")[0]}*` : '*' |
| | extraPattern = '/' + (searchTerm.split(">")[1] ? `*${searchTerm.split(">")[1]}*` : '*') |
| | _onlyDirectories = false |
| | } else { |
| | pattern = `*${searchTerm}*` |
| | } |
| | } else { |
| | pattern = '*' |
| | } |
| |
|
| | const files = fg.globSync([`networks/${searchType}/**/${pattern}${extraPattern}`], { onlyDirectories: _onlyDirectories, dot: false, caseSensitiveMatch: false, stats: true }) |
| |
|
| | images = files.map(file => { |
| | |
| | |
| |
|
| | let filename = (file.name.indexOf("." + imgExt) > -1) ? file.name : file.name + "." + imgExt |
| | let path = file.path.replace(file.name, '').replace('networks/', '').toLowerCase() |
| |
|
| | |
| | return { |
| | filename: filename, |
| | path: path, |
| | } |
| | }) |
| | res.json(images) |
| |
|
| | } else if (searchType == "poses") { |
| | |
| |
|
| | let pattern = '' |
| | let extraPattern = '' |
| | let _onlyDirectories = false |
| | let ext = "png" |
| |
|
| | if (searchTerm) { |
| | if (searchTerm.split(">").length > 1) { |
| | pattern = searchTerm.split(">")[0] ? `*${searchTerm.split(">")[0]}*` : '*' |
| | extraPattern = '/' + (searchTerm.split(">")[1] ? `*${searchTerm.split(">")[1]}*` : '*') |
| | extraPattern += "." + ext |
| | } else { |
| | pattern = `*${searchTerm}*` |
| | extraPattern += "." + ext |
| | } |
| | } else { |
| | pattern = '*' |
| | extraPattern += "." + ext |
| | } |
| |
|
| | const files = fg.globSync([`networks/${searchType}/*/${pattern}${extraPattern}`], { onlyDirectories: _onlyDirectories, dot: false, caseSensitiveMatch: false, stats: true }) |
| |
|
| | images = files.flatMap(file => { |
| |
|
| | let filename = (file.name.indexOf("." + ext) > -1) ? file.name : file.name + "." + ext |
| | let path = file.path.replace(file.name, '').replace('networks/', '').toLowerCase() |
| | |
| | let name = /poses\/(.+?)\//.exec(path)[1] |
| | |
| | if (filename.match(/\. \([0-9]+\)\./)) { return [] } |
| |
|
| | |
| | return { |
| | filename: filename, |
| | path: path, |
| | name: name |
| | } |
| | }) |
| | res.json(images) |
| |
|
| | } else { |
| | |
| | let ext = null |
| | if (searchType == "lora" || searchType == "checkpoints") { |
| | ext = "safetensors" |
| | } else if (searchType == "embeddings" || searchType == "hypernets") { |
| | ext = "(pt|safetensors)" |
| | } else { |
| | return res.status(400).send({ |
| | message: 'Invalid type requested.' |
| | }); |
| | } |
| |
|
| | let pattern = '' |
| | let extraPattern = '' |
| |
|
| | if (searchTerm) { |
| | if (searchTerm.split(">").length > 1) { |
| | pattern = searchTerm.split(">")[0] ? `*${searchTerm.split(">")[0]}*` : '*' |
| | extraPattern = '/' + (searchTerm.split(">")[1] ? `*${searchTerm.split(">")[1]}*` : '*') |
| | } else { |
| | pattern = `*${searchTerm}*` |
| | extraPattern = "." + ext |
| | } |
| | } else { |
| | pattern = '*' |
| | extraPattern = "." + ext |
| | } |
| |
|
| | const files = fg.globSync([`networks/${searchType}/**/${pattern}${extraPattern}`], { dot: false, caseSensitiveMatch: false, stats: true }) |
| |
|
| | images = files.map(file => { |
| | |
| | |
| |
|
| | let filematch = file.name.match(/(.*)\.(.*?)$/) |
| | let filename = filematch ? filematch[1] + "." + imgExt : "" |
| | let noext = filematch ? filematch[1] : "" |
| | let words = noext.split(' ') |
| | let path = file.path.replace(file.name, '').replace('networks/', '').toLowerCase() |
| | let name = noext.match(/^(.*)_([0-9a-zA-Z]+)\s/) |
| | name = name ? name[1] : null |
| | let author = noext.match(/_([0-9a-zA-Z]+)\s/) |
| | author = author ? author[1] : null |
| | let hashtagWords = words.filter(word => word.startsWith("#")) |
| | let tags = hashtagWords.map(word => word.slice(1)) |
| | let weight = noext.match(/{(?:[0-9]*\.?[0-9]+\s?-)?([0-9]*\.?[0-9]+)}/) |
| | weight = weight ? weight[1] : "1.0" |
| |
|
| | |
| | let keywords = filename.match(/\[(.*)\]/) |
| |
|
| | |
| | if (keywords) { |
| | keywords = keywords[1] |
| | keywords = keywords.replaceAll(/©️/g, ':') |
| | keywords = keywords.replaceAll(/≻/g, '>') |
| | keywords = keywords.replaceAll(/≺/g, '<') |
| | keywords = keywords.replaceAll(/(\w+?) \((\w+?)\)/gi, '$1 \\($2\\)') |
| | keywords = keywords.replaceAll('[', '') |
| | keywords = keywords.replaceAll(']', ', ') |
| | } |
| |
|
| | let prompt = null |
| | if (searchType == "lora") { |
| | prompt = `${keywords ? keywords+" " : ""}<lora:${noext}:${weight}>` |
| | } else if (searchType == "hypernets") { |
| | prompt = `${keywords ? keywords+" " : ""}<hypernet:${noext}:${weight}>` |
| | } else { |
| | prompt = noext |
| | } |
| |
|
| | |
| | return { |
| | filename: filename, |
| | path: path, |
| | name: name, |
| | author: author, |
| | tags: tags, |
| | keywords: keywords, |
| | weight: weight, |
| | prompt: prompt, |
| | mtimeMs: file.stats.mtimeMs, |
| | mtime: file.stats.mtime, |
| | } |
| | }) |
| |
|
| | res.json(images) |
| | } |
| |
|
| | } |
| | }) |
| |
|
| | |
| | app.get('/moreImages', (req, res) => { |
| |
|
| | const search = req.query.search || res.status(400).send({ |
| | message: 'Missing query.' |
| | }); |
| | const type = req.query.type |
| |
|
| | |
| | const filteredSearch = search.replaceAll('$','\\$') |
| | .replaceAll('^','\\^') |
| | .replaceAll('?','\\?') |
| | .replaceAll('(','\\(') |
| | .replaceAll(')','\\)') |
| | .replaceAll('[','\\[') |
| | .replaceAll(']','\\]') |
| | .replaceAll('{','\\{') |
| | .replaceAll('}','\\}') |
| |
|
| | const ext = (type == "poses") ? "png" : imgExt |
| | const noext = filteredSearch.substring(filteredSearch.lastIndexOf('/') + 1).replace('.' + ext, '') |
| | const searchPath = filteredSearch.substring(0, filteredSearch.lastIndexOf('/')) |
| |
|
| | |
| | |
| | const query = `networks/${searchPath}/${noext}(.*|).${ext}` |
| | const queryFolder = `networks/${searchPath}/${noext}/*.${ext}` |
| | const files = fg.globSync([query, queryFolder], { dot: false, caseSensitiveMatch: false, stats: true }) |
| |
|
| | const images = files.map(file => { |
| | const path = file.path.replace(file.name, '').replace('networks/', '').toLowerCase() |
| |
|
| | |
| | return { |
| | filename: file.name, |
| | path: path, |
| | mtimeMs: file.stats.mtimeMs, |
| | mtime: file.stats.mtime, |
| | } |
| | }) |
| |
|
| | res.json(images) |
| | }) |
| |
|
| | app.listen(port, () => { |
| | console.log(`Server running at http://localhost:${port}`) |
| | }) |