forked from oat/in-the-database-2
		
	Compare commits
	
		
			16 commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 88fc57da82 | ||
|  | 564d71c48f | ||
|  | 4cbe252852 | ||
|  | 0a150ad343 | ||
|  | f113c472fd | ||
|  | 96facbf2e2 | ||
|  | df6c1545af | ||
|  | e218255441 | ||
|  | 36f4da4a28 | ||
|  | ef58af8a9a | ||
|  | 795f983721 | ||
|  | 6b07ef943d | ||
|  | 73d5962c5c | ||
|  | 1ed6dc6185 | ||
|  | 64446588c9 | ||
| dc88ad2b75 | 
					 14 changed files with 677 additions and 369 deletions
				
			
		
							
								
								
									
										3
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -3,4 +3,5 @@ node_modules | |||
| built | ||||
| config/config.json | ||||
| *.log | ||||
| .env | ||||
| .env | ||||
| storage/files/* | ||||
|  | @ -1,6 +1,8 @@ | |||
|  | ||||
| 
 | ||||
| a database site for notitg modcharts, currently very very unfinished, basically just a boilerplate | ||||
| a database site for notitg modcharts, currently very very unfinished | ||||
| 
 | ||||
| you can login with discord, upload and download files, thats about it, but im still proud of it | ||||
| 
 | ||||
| ## setup | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								assets/icon.ico
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icon.ico
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 70 KiB | 
							
								
								
									
										682
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										682
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										18
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								package.json
									
										
									
									
									
								
							|  | @ -12,20 +12,24 @@ | |||
|   "license": "MIT", | ||||
|   "dependencies": { | ||||
|     "@types/express": "github:types/express", | ||||
|     "@types/mongoose": "^5.7.36", | ||||
|     "adm-zip": "^0.5.1", | ||||
|     "axios": "^0.20.0", | ||||
|     "connect-mongo": "^3.2.0", | ||||
|     "dotenv": "^8.2.0", | ||||
|     "express": "^4.17.1", | ||||
|     "express-fileupload": "^1.2.0", | ||||
|     "mongoose": "^5.10.2", | ||||
|     "express-session": "^1.17.1", | ||||
|     "mongoose": "^5.11.8", | ||||
|     "mongoose-int32": "^0.4.1", | ||||
|     "node-stream-zip": "^1.11.3", | ||||
|     "typescript": "^4.0.2", | ||||
|     "serve-favicon": "^2.5.0", | ||||
|     "typescript": "^4.1.3", | ||||
|     "uuid": "^8.3.2", | ||||
|     "winston": "^3.3.3" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@typescript-eslint/eslint-plugin": "^4.0.1", | ||||
|     "@typescript-eslint/parser": "^4.0.1", | ||||
|     "eslint": "^7.8.1" | ||||
|     "@types/express-session": "^1.17.3", | ||||
|     "@typescript-eslint/eslint-plugin": "^4.11.0", | ||||
|     "@typescript-eslint/parser": "^4.11.0", | ||||
|     "eslint": "^7.16.0" | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -1,14 +1,14 @@ | |||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| 
 | ||||
|     <head> | ||||
|         <meta charset="UTF-8"> | ||||
|         <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|         <title>Index</title> | ||||
|     </head> | ||||
| 	<head> | ||||
| 		<meta charset="UTF-8"> | ||||
| 		<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
| 		<title>Index</title> | ||||
| 	</head> | ||||
| 
 | ||||
|     <body> | ||||
|         <h1>Hi</h1> | ||||
|     </body> | ||||
| 	<body> | ||||
| 		<h1>Hi</h1> | ||||
| 	</body> | ||||
| 
 | ||||
| </html> | ||||
|  | @ -1,36 +1,42 @@ | |||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| 
 | ||||
|     <head> | ||||
|         <meta charset="UTF-8"> | ||||
|         <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|         <title>list</title> | ||||
|     </head> | ||||
| 	<head> | ||||
| 		<meta charset="UTF-8"> | ||||
| 		<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
| 		<title>list</title> | ||||
| 	</head> | ||||
| 
 | ||||
|     <body> | ||||
|         <div id="doc-list"> | ||||
|         </div> | ||||
| 	<body> | ||||
| 		<div id="doc-list"> | ||||
| 		</div> | ||||
| 
 | ||||
|         <script src="https://cdn.jsdelivr.net/npm/axios@0.20.0/dist/axios.min.js"></script> | ||||
|         <script> | ||||
|             axios.get('/api/list').then(({ data }) => { | ||||
|                 console.log(data); | ||||
|                 const el = document.getElementById('doc-list'); | ||||
|                 for (const doc of data) { | ||||
|                     let p = document.createElement('p'); | ||||
|                     p.innerText = `${doc.artist} - ${doc.title} by ${doc.credit}`; | ||||
|                     el.insertAdjacentElement('beforeend', p); | ||||
| 		<script src="https://cdn.jsdelivr.net/npm/axios@0.20.0/dist/axios.min.js"></script> | ||||
| 		<script> | ||||
| 			axios.get('/api/list').then(({ data }) => { | ||||
| 				console.log(data); | ||||
| 				const el = document.getElementById('doc-list'); | ||||
| 				for (const doc of data) { | ||||
| 					let p = document.createElement('p'); | ||||
| 					p.innerHTML = `<b>${doc.artist} - ${doc.title}</b> by ${doc.credit}\nuploaded by ${doc.uploaderJSON.username}#${doc.uploaderJSON.discriminator}\n<a href="files/${doc.id}.zip">download</a>`; | ||||
| 
 | ||||
|                     let charts = document.createElement('ul'); | ||||
|                     for (const chart of doc.charts) { | ||||
|                         let l = document.createElement('li'); | ||||
|                         l.innerText = `${chart.difficulty} ${chart.rating} - ${chart.name}` | ||||
|                         charts.insertAdjacentElement('beforeend', l); | ||||
|                     } | ||||
|                     el.insertAdjacentElement('beforeend', charts); | ||||
|                 } | ||||
|             }); | ||||
|         </script> | ||||
|     </body> | ||||
| 					if (doc.editable) { | ||||
| 						p.innerHTML += ` <a href="../${doc.id}/edit">edit</a>` | ||||
| 					} | ||||
| 
 | ||||
| 					el.insertAdjacentElement('beforeend', p); | ||||
| 
 | ||||
| 					let charts = document.createElement('ul'); | ||||
| 					for (const chart of doc.charts) { | ||||
| 						let l = document.createElement('li'); | ||||
| 						l.innerHTML = `${chart.difficulty} ${chart.rating} - <b>${chart.name}</b><br>` + | ||||
| 							`${chart.steps} steps, ${chart.mines} mines, ${chart.jumps} jumps, ${chart.hands} hands, ${chart.holds} holds, ${chart.rolls} rolls` | ||||
| 						charts.insertAdjacentElement('beforeend', l); | ||||
| 					} | ||||
| 					el.insertAdjacentElement('beforeend', charts); | ||||
| 				} | ||||
| 			}); | ||||
| 		</script> | ||||
| 	</body> | ||||
| 
 | ||||
| </html> | ||||
|  | @ -19,7 +19,7 @@ | |||
| 				const file = document.getElementById('file'); | ||||
| 				if (file.files.length) { | ||||
| 					console.log(file.files[0]); | ||||
| 	 | ||||
| 
 | ||||
| 					const formData = new FormData(); | ||||
| 					formData.append('file', file.files[0]); | ||||
| 					try { | ||||
|  |  | |||
							
								
								
									
										47
									
								
								src/auth.ts
									
										
									
									
									
								
							
							
						
						
									
										47
									
								
								src/auth.ts
									
										
									
									
									
								
							|  | @ -1,3 +1,6 @@ | |||
| import { User } from './schema'; | ||||
| import * as uuid from 'uuid'; | ||||
| 
 | ||||
| const API_ENDPOINT = 'https://discord.com/api/v6'; | ||||
| 
 | ||||
| const axios = require('axios').default; | ||||
|  | @ -5,6 +8,7 @@ const axios = require('axios').default; | |||
| export function run(app) { | ||||
| 	app.get('/discordauth', async (req, res) => { | ||||
| 		const code = req.query.code; | ||||
| 		const url = `http://${req.headers.host}/discordauth`; | ||||
| 
 | ||||
| 		if (code) { | ||||
| 			try { | ||||
|  | @ -13,7 +17,7 @@ export function run(app) { | |||
| 					client_secret: process.env.DISCORD_OAUTH_CLIENTSECRET, | ||||
| 					grant_type: 'authorization_code', | ||||
| 					code: code, | ||||
| 					redirect_uri: 'http://localhost:8080/discordauth', | ||||
| 					redirect_uri: url, | ||||
| 					scope: 'identify' | ||||
| 				}); | ||||
| 	 | ||||
|  | @ -28,12 +32,49 @@ export function run(app) { | |||
| 						authorization: `${postRes.data.token_type} ${postRes.data.access_token}` | ||||
| 					} | ||||
| 				}); | ||||
| 				res.send(`hi ${userInfo.data.username}#${userInfo.data.discriminator}<br><img src="https://media.discordapp.net/avatars/${userInfo.data.id}/${userInfo.data.avatar}.png">`); | ||||
| 
 | ||||
| 				const users = await User.find({id: String(userInfo.data.id)}); | ||||
| 				let userUuid = ''; | ||||
| 
 | ||||
| 				if (users.length === 0) { | ||||
| 					let newUuid = uuid.v4(); | ||||
| 
 | ||||
| 					while (User.find({uuid: newUuid})[0]) { | ||||
| 						newUuid = uuid.v4(); | ||||
| 					} | ||||
| 
 | ||||
| 					const newUser = new User({ | ||||
| 						id: String(userInfo.data.id), | ||||
| 						createdAt: new Date(), | ||||
| 
 | ||||
| 						username: userInfo.data.username, | ||||
| 						discriminator: userInfo.data.discriminator, | ||||
| 						avatar: userInfo.data.avatar, | ||||
| 
 | ||||
| 						uuid: newUuid, | ||||
| 					}); | ||||
| 
 | ||||
| 					userUuid = newUser.get('uuid'); | ||||
| 					newUser.save(); | ||||
| 				} else { | ||||
| 					const user = users[0]; | ||||
| 					userUuid = user.get('uuid'); | ||||
| 
 | ||||
| 					user.set('id', String(userInfo.data.id)); | ||||
| 					user.set('username', userInfo.data.username); | ||||
| 					user.set('discriminator', userInfo.data.discriminator); | ||||
| 					user.set('avatar', userInfo.data.avatar); | ||||
| 				} | ||||
| 
 | ||||
| 				req.session!.discord = userInfo.data; | ||||
| 				req.session!.uuid = userUuid; | ||||
| 				res.send(`logged in as ${userInfo.data.username}#${userInfo.data.discriminator}<br><img src="https://media.discordapp.net/avatars/${userInfo.data.id}/${userInfo.data.avatar}.png"><br>ur useruuid is ${userUuid}`); | ||||
| 			} catch(err) { | ||||
| 				res.send(`whoooops<br>${err}`); | ||||
| 				console.error(err); | ||||
| 			} | ||||
| 		} else { | ||||
| 			res.send(`<a href="https://discord.com/api/oauth2/authorize?client_id=${process.env.DISCORD_OAUTH_CLIENTID}&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fdiscordauth&response_type=code&scope=identify">Click here!!</a>`); | ||||
| 			res.send(`<a href="https://discord.com/api/oauth2/authorize?client_id=${process.env.DISCORD_OAUTH_CLIENTID}&redirect_uri=${encodeURI(url)}&response_type=code&scope=identify">Click here!!</a>`); | ||||
| 		} | ||||
| 	}); | ||||
| } | ||||
							
								
								
									
										38
									
								
								src/index.ts
									
										
									
									
									
								
							
							
						
						
									
										38
									
								
								src/index.ts
									
										
									
									
									
								
							|  | @ -3,9 +3,12 @@ import * as mongoose from 'mongoose'; | |||
| import * as fs from 'fs'; | ||||
| import * as winston from 'winston'; | ||||
| import * as fileUpload from 'express-fileupload'; | ||||
| import * as session from 'express-session'; | ||||
| import * as favicon from 'serve-favicon'; | ||||
| const MongoStore = require('connect-mongo')(session); | ||||
| 
 | ||||
| import * as format from './lib/format'; | ||||
| import { File } from './schema'; | ||||
| import { File, User } from './schema'; | ||||
| 
 | ||||
| import * as upload from './upload'; | ||||
| import * as auth from './auth'; | ||||
|  | @ -52,8 +55,22 @@ db.then(() => { | |||
| 
 | ||||
| 	// @ts-ignore
 | ||||
| 	app.use(express.urlencoded({extended: true})); | ||||
| 	app.use(favicon('assets/icon.ico')); | ||||
| 	app.use(fileUpload({limits: { fileSize: 50 * 1024 * 1024 }})); | ||||
| 	app.use(express.static('public', {extensions:  ['html', 'htm']})); | ||||
| 	app.use(express.static('storage', {extensions:  ['zip']})); | ||||
| 	app.use(session({ | ||||
| 		name: 'funnyuserdata', | ||||
| 		secret: 'wenis', | ||||
| 		store: new MongoStore({ mongooseConnection: mongoose.connection }), | ||||
| 		cookie: { | ||||
| 			maxAge: 1000 * 60 * 60 * 24 * 365 * 10, // 10 years
 | ||||
| 			httpOnly: true, | ||||
| 			sameSite: 'lax', | ||||
| 		}, | ||||
| 		resave: false, | ||||
| 		saveUninitialized: true | ||||
| 	})); | ||||
| 	app.use('/assets', express.static('assets')); | ||||
| 
 | ||||
| 	app.set('db', db); | ||||
|  | @ -63,8 +80,23 @@ db.then(() => { | |||
| 	upload.run(app); | ||||
| 	auth.run(app); | ||||
| 
 | ||||
| 	app.get('/api/list', async (req, res) => { // only for testing
 | ||||
| 		const docs = await File.find({}); | ||||
| 	app.get('/api/list', async (req, res) => { | ||||
| 		const files = await File.find({}); | ||||
| 
 | ||||
| 		const docs = []; | ||||
| 		for (const doc of files) { | ||||
| 			const d: any = doc.toJSON(); | ||||
| 
 | ||||
| 			d.editable = false; | ||||
| 			if (req.session) d.editable = req.session.uuid === d.uploader; | ||||
| 
 | ||||
| 			const user = await User.find({uuid: d.uploader}); | ||||
| 			if (user) { | ||||
| 				d.uploaderJSON = user[0].toJSON(); // this is built upon 20 layers of metajank and i despise it
 | ||||
| 				docs.push(d); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// TODO: filter out _id and __v? possibly more
 | ||||
| 		res.send(docs); | ||||
| 	}); | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| export function parseSM(data: string) { | ||||
| 	data = data.replace(/[\n\r]/g,''); | ||||
| 
 | ||||
| 	// steps
 | ||||
| 	const difficulties = []; | ||||
| 	const steps = data.split('#NOTES:'); | ||||
|  | @ -18,11 +16,25 @@ export function parseSM(data: string) { | |||
| 				diff.rating = Number(stepsSplit[3]); | ||||
| 				diff.radarvalues = stepsSplit[4].split(',').map(v => Number(v)); | ||||
| 
 | ||||
| 				const chart = stepsSplit[5]; | ||||
| 				diff.rawChart = chart; | ||||
| 
 | ||||
| 				diff.steps = chart.split(/[124]/g).length - 1; | ||||
| 				diff.mines = chart.split('M').length - 1; | ||||
| 				diff.jumps = chart.split(/[124]0{0,2}[124]/g).length - 1; | ||||
| 				diff.hands = chart.split(/[124]0{0,1}[124]0{0,1}[124]/g).length - 1; | ||||
| 				diff.holds = chart.split('2').length - 1; | ||||
| 				diff.rolls = chart.split('4').length - 1; | ||||
| 
 | ||||
| 				diff.steps -= diff.jumps; // jumps are counted as 1 step
 | ||||
| 
 | ||||
| 				difficulties.push(diff); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	data = data.replace(/[\n\r]/g,''); | ||||
| 
 | ||||
| 	// metadata
 | ||||
| 	const lines = data.split(';').filter(l => l.startsWith('#')); | ||||
| 	const obj: any = {}; | ||||
|  | @ -41,7 +53,7 @@ export function parseSM(data: string) { | |||
| 				const map = {}; | ||||
| 
 | ||||
| 				for (const i in keys) { | ||||
| 					map[Number(keys[i])] = Number(values[i]); // afaik maps are only numbers?
 | ||||
| 					map[String(Number(keys[i])).replace('.', ',')] = Number(values[i]); // afaik maps are only numbers?
 | ||||
| 				} | ||||
| 
 | ||||
| 				value = map; | ||||
|  |  | |||
|  | @ -1,10 +0,0 @@ | |||
| import * as fs from 'fs'; | ||||
| 
 | ||||
| export function returnStatic(page) { | ||||
| 	return (req, res) => { | ||||
| 		fs.readFile(`src/html/${page}`, 'utf8', (err, data) => { | ||||
| 			if (err) throw err; | ||||
| 			res.send(data); | ||||
| 		}); | ||||
| 	}; | ||||
| } | ||||
|  | @ -1,39 +1,118 @@ | |||
| /* eslint-disable no-unused-vars */ | ||||
| import * as mongoose from 'mongoose'; | ||||
| 
 | ||||
| const Schema = mongoose.Schema; | ||||
|   | ||||
| export enum SMVersion { | ||||
| 	OPENITG, | ||||
| 	FUCKEXE, | ||||
| 	NOTITG_V1, | ||||
| 	NOTITG_V2, | ||||
| 	NOTITG_V3, | ||||
| 	NOTITG_V3_1, | ||||
| 	NOTITG_V4, | ||||
| 	NOTITG_V4_0_1, | ||||
| 	STEPMANIA_3_95, | ||||
| 	STEPMANIA_5_0, | ||||
| 	STEPMANIA_5_1, | ||||
| 	STEPMANIA_5_2, | ||||
| 	STEPMANIA_5_3, | ||||
| } | ||||
| 
 | ||||
| const Sample = new Schema({ | ||||
| 	start: {type: Number, default: 0}, | ||||
| 	length: {type: Number, default: 0} | ||||
| }); | ||||
| 
 | ||||
| const UserRating = new Schema({ | ||||
| 	rating: {type: Number, default: 0}, | ||||
| 	createdAt: Date, | ||||
| 	user: {type: String, default: '00000000-0000-4000-a000-000000000000'} | ||||
| }); | ||||
| 
 | ||||
| const Chart = new Schema({ | ||||
| 	type: {type: String, default: 'dance-single'}, | ||||
| 	name: {type: String, default: ''}, | ||||
| 	difficulty: {type: String, default: 'Challenge'}, | ||||
| 	radarvalues: [Number], | ||||
| 
 | ||||
| 	rating: {type: Number, default: 0}, | ||||
| 	radarvalues: [Number] | ||||
| 	ratingsVote: {type: [UserRating], default: []}, | ||||
| 
 | ||||
| 	spoilered: {type: Boolean, default: false}, | ||||
| 	hidden: {type: Boolean, default: false}, | ||||
| 
 | ||||
| 	steps: {type: Number, default: 0}, | ||||
| 	mines: {type: Number, default: 0}, | ||||
| 	jumps: {type: Number, default: 0}, | ||||
| 	hands: {type: Number, default: 0}, | ||||
| 	holds: {type: Number, default: 0}, | ||||
| 	rolls: {type: Number, default: 0}, | ||||
| }); | ||||
| 
 | ||||
| const Comment = new Schema({ | ||||
| 	author: {type: String, default: '00000000-0000-4000-a000-000000000000'}, | ||||
| 	createdAt: Date, | ||||
| 	content: {type: String, default: ''} | ||||
| }); | ||||
| 
 | ||||
| const FileSchema = new Schema({ | ||||
| 	id: {type: Number, default: 0}, | ||||
| 
 | ||||
| 	title: {type: String, default: 'unknown'}, | ||||
| 	titleTranslit: String, | ||||
| 	artist: {type: String, default: 'unknown'}, | ||||
| 	artistTranslit: String, | ||||
| 	subtitle: String, | ||||
| 	subtitleTranslit: String, | ||||
| 
 | ||||
| 	credit: String, | ||||
| 	uploader: {type: String, default: '00000000-0000-4000-a000-000000000000'}, | ||||
| 
 | ||||
| 	sample: Sample, | ||||
| 	bpms: {type: Object, default: {'0': 0}}, | ||||
| 	charts: [Chart] | ||||
| 
 | ||||
| 	charts: {type: [Chart], default: []}, | ||||
| 
 | ||||
| 	description: {type: String, default: ''}, | ||||
| 	createdAt: Date, | ||||
| 	smVersion: {type: Number, default: 0}, // see SMVersion enum
 | ||||
| 	ytLink: String, | ||||
| 	customLink: String, | ||||
| 	hidden: {type: Boolean, default: false}, | ||||
| 
 | ||||
| 	comments: {type: [Comment], default: []}, | ||||
| }); | ||||
| 
 | ||||
| export const File = mongoose.model('File', FileSchema); | ||||
| 
 | ||||
| const UserSchema = new Schema({ // this is pretty much just a discord user lol
 | ||||
| 	id: String, // cus longass number
 | ||||
| 	approved: Boolean | ||||
| 	id: {type: String, default: 'notgiven!!!!!!!!!!!!'}, // discord id, cus longass number
 | ||||
| 	createdAt: Date, | ||||
| 
 | ||||
| 	// caching
 | ||||
| 	username: {type: String, default: 'User'}, | ||||
| 	discriminator: {type: String, default: '0000'}, | ||||
| 	avatar: String, | ||||
| 
 | ||||
| 	// used internally
 | ||||
| 	uuid: {type: String, default: '00000000-0000-4000-a000-000000000000'}, | ||||
| 
 | ||||
| 	approvedUpload: {type: Boolean, default: false}, | ||||
| 	approvedRate: {type: Boolean, default: false}, | ||||
| 	approvedComment: {type: Boolean, default: false}, | ||||
| }); | ||||
| 
 | ||||
| export const User = mongoose.model('User', UserSchema); | ||||
| export const User = mongoose.model('User', UserSchema); | ||||
| 
 | ||||
| const PackSchema = new Schema({ | ||||
| 	author: {type: String, default: '00000000-0000-4000-a000-000000000000'}, | ||||
| 	files: {type: [Number], default: []}, // ids
 | ||||
| 	name: {type: String, default: 'Pack'}, | ||||
| 	description: {type: String, default: ''}, | ||||
| 	createdAt: Date, | ||||
| 
 | ||||
| 	hidden: {type: Boolean, default: false}, | ||||
| }); | ||||
| 
 | ||||
| export const Pack = mongoose.model('Pack', PackSchema); | ||||
|  | @ -1,54 +1,75 @@ | |||
| import { tmpdir } from 'os'; | ||||
| import * as fs from 'fs'; | ||||
| const StreamZip = require('node-stream-zip'); | ||||
| import * as AdmZip from 'adm-zip'; | ||||
| 
 | ||||
| import { returnStatic } from './lib/util'; | ||||
| import { parseSM } from './lib/smparse'; | ||||
| import { File } from './schema'; | ||||
| import { File, User } from './schema'; | ||||
| 
 | ||||
| export function run(app) { | ||||
| 	const logger = app.get('logger'); | ||||
| 	 | ||||
| 	app.post('/api/upload', async (req, res) => { // only for testing, very abusable
 | ||||
| 		if (!req.files) return res.status(400).send('No files were given'); | ||||
| 		if (!req.session.uuid) return res.status(401).send('Not authorized, use /discordauth'); | ||||
| 
 | ||||
| 		const user = (await User.find({uuid: req.session.uuid}))[0]; | ||||
| 		if (!user) return res.status(401).send('User doesn\'t exist, try re-logging in'); | ||||
| 		if (!user.get('approvedUpload')) return res.status(403).send('Your account is not allowed to upload files! Contact a moderator to verify your account'); | ||||
| 		 | ||||
| 		const file = req.files.file; | ||||
| 	 | ||||
| 		if (file.mimetype !== 'application/zip' && file.mimetype !== 'application/x-zip-compressed') return res.status(400).send('Invalid filetype'); | ||||
| 
 | ||||
| 		const dir = tmpdir() + '/' + file.md5; | ||||
| 		fs.writeFile(dir, file.data, (err) => { | ||||
| 		fs.writeFile(dir, file.data, async (err) => { | ||||
| 			if (err) throw err; | ||||
| 
 | ||||
| 			const zip = new StreamZip({ | ||||
| 				file: dir, | ||||
| 				storeEntries: true | ||||
| 			}); | ||||
| 			try { | ||||
| 				const zip = new AdmZip(dir); | ||||
| 				const zipEntries = zip.getEntries(); | ||||
| 
 | ||||
| 			zip.on('ready', () => { | ||||
| 				const smFile = Object.values(zip.entries()).find((f: any) => | ||||
| 					!f.isDirectory && (f.name.endsWith('.sm')) | ||||
| 				const smFile: any = Object.values(zipEntries).find((f: any) => | ||||
| 					!f.isDirectory && (f.entryName.endsWith('.sm')) | ||||
| 				); | ||||
| 
 | ||||
| 				if (!smFile) { | ||||
| 					res.status(400).send('No .sm found'); | ||||
| 				} else { | ||||
| 					const data = zip.entryDataSync((smFile as any).name); | ||||
| 					const data = smFile.getData().toString('utf8'); | ||||
| 					const chart = parseSM(data.toString()); | ||||
| 
 | ||||
| 					logger.info(`${chart.artist} - ${chart.title} was just uploaded`); | ||||
| 
 | ||||
| 					const file = new File(chart); | ||||
| 					file.save(); | ||||
| 					let id = 0; | ||||
| 					for (const f of await File.find({})) { | ||||
| 						id = Math.max(Number(f.id), id); | ||||
| 					} | ||||
| 					chart.id = id + 1; | ||||
| 
 | ||||
| 					// TODO: filter out _id and __v? possibly more
 | ||||
| 					res.send(chart); | ||||
| 					chart.uploader = req.session.uuid; | ||||
| 
 | ||||
| 					chart.createdAt = new Date(); | ||||
| 
 | ||||
| 					fs.writeFile('./storage/files/' + (id + 1) + '.zip', file.data, (err) => { | ||||
| 						if (err) throw err; | ||||
| 
 | ||||
| 						const file = new File(chart); | ||||
| 						file.save(); | ||||
| 
 | ||||
| 						// TODO: filter out _id and __v? possibly more
 | ||||
| 						res.send(chart); | ||||
| 					}); | ||||
| 				} | ||||
| 
 | ||||
| 				zip.close(); | ||||
| 				fs.unlink(dir, (err) => { | ||||
| 					if (err) throw err; | ||||
| 				}); | ||||
| 			}); | ||||
| 			} catch(err) { | ||||
| 				logger.error(err.toString()); | ||||
| 				console.error(err); | ||||
| 				res.status(400); | ||||
| 				res.send(err.toString()); | ||||
| 			} | ||||
| 		}); | ||||
| 	}); | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue