ソースを参照

Refactor of promises, added queue management

¨José 5 年 前
コミット
050b27a3ac
1 ファイル変更106 行追加121 行削除
  1. 106 121
      downloadBot.js

+ 106 - 121
downloadBot.js

@@ -1,35 +1,106 @@
-const Telegram = require('telegraf/telegram');
-const Telegraf = require('telegraf');
-const fs = require('fs');
-const https = require('https');
-const telegram = new Telegram(process.env.BOT_TOKEN);
-const bot = new Telegraf(process.env.BOT_TOKEN);
-const downloadPrefix = process.env.DOWNLOAD_PREFIX;
+const Telegram = require('telegraf/telegram')
+const Telegraf = require('telegraf')
+const fs = require('fs')
+const https = require('https')
+const telegram = new Telegram(process.env.BOT_TOKEN)
+const bot = new Telegraf(process.env.BOT_TOKEN)
+const downloadPrefix = process.env.DOWNLOAD_PREFIX
 const musicDir = 'music'
-const videoDir = 'video'
-const documentDir = 'downloads'
-const admin = 170276072;
-const langData=fs.readFileSync('./string/lang.json', 'utf8');
-const language = JSON.parse(langData);
-var lang = language.en;
+const langData = fs.readFileSync('./string/lang.json', 'utf8')
+const language = JSON.parse(langData)
+const API_URL = "https://api.telegram.org/file/bot" + process.env.BOT_TOKEN
+const debug = require('debug')('app')
+const Queue = require('bull')
+var lang = language.en
+const queue = new Queue('rateLimited', {
+	limiter: {
+		max: 2,
+		duration: 60000,
+		bounceBack: false
+	}
+})
+const options = {
+	delay: 60000, // 1 min in ms
+	attempts: 2
+}
+
+// ----------------------------------------------------------------------------
+
+queue.process(async (job) => {
+	return await saveFile(job.data.file_id, job.data.destination,
+		job.data.filename).then(() => {
+		const text = 'File ' + job.data.filename + ' downloaded.'
+		telegram.sendMessage(job.data.chat_id, text)
+	}).catch(error => {
+		const text = 'Error downloading file: ' + error
+		telegram.sendMessage(job.data.chat_id, text)
+	})
+})
+
+// ----------------------------------------------------------------------------
+
+function cleanString(string, additionalChars) {
+	const chars = "!@#$^&%*()+=[]\/{}|:<>?,'–" + additionalChars
+	var result = string.normalize('NFD').trim()
+		.replace(/[\u0300-\u036f]/g, '')
+	for (var i=0; i < chars.length; i++) {
+		result = result.replace(new RegExp("\\" + chars[i], 'gi'), '')
+	}
+	return result 
+}
 
+// ----------------------------------------------------------------------------
+
+function saveFile(file_id, dest, filename) {
+	return new Promise(function(resolve, reject){
+		if (!fs.existsSync(dest)){ fs.mkdirSync(dest, true) }
+		const path = dest + filename
+		const promise = telegram.getFile(file_id)
+		promise.then(res => {
+			const url = API_URL + '/' + res.file_path
+			https.get(url, response => {
+				if(response.statusCode != 200){
+					debug('Error downloading file: %s', response.statuscode)
+					reject()
+				}else{
+					const file = fs.createWriteStream(path)
+					response.pipe(file)
+					file.on('finish', function(){
+						file.close()
+						debug('File saved in: "%s"', path)
+						resolve()
+					}).on('error', err =>{
+						fs.unlink(path) 
+						debug(err)
+						reject()
+					})
+				}
+			})
+		}).catch(function(error){
+			debug('[SaveFile,Promise][Error]: %s', error)
+			reject()
+		})
+	})
+}
+
+// ----------------------------------------------------------------------------
 
 bot.start( (ctx) => {
-  console.log('started:', ctx.from.id)
+  debug('Started: %s', ctx.from.id)
   return ctx.reply(lang.welcome)
 })
 
 // ----------------------------------------------------------------------------
 
 bot.command('spanish', (ctx) => {
-  lang = language.es;
+  lang = language.es
   ctx.reply(lang.langChanged)
 })
 
 // ----------------------------------------------------------------------------
 
 bot.command('english', (ctx) => {
-  lang = language.en;
+  lang = language.en
   ctx.reply(lang.langChanged)
 })
 
@@ -44,113 +115,27 @@ bot.command('help', (ctx) => ctx.reply(lang.help))
 // ----------------------------------------------------------------------------
 
 bot.on('audio', (ctx) => {
-	console.log('Audio message received from: ', ctx.from.id)
-	telegram.getFile( ctx.message.audio.file_id, (ctx) => { 
-		console.log('audio_id sent to TG: ', ctx.message.audio.file_id)
-	})
-
-	const specialChars = "!@#$^&%*()+=[]\/{}|:<>?,.' "
 	const audio = ctx.message.audio
-	var filename = audio.performer + "-" + audio.title
-	for (var i = 0; i < specialChars.length; i++) {
-		filename = filename.replace(new RegExp("\\" + specialChars[i], 'gi'), '_')
-	}
-	filename = filename + ".mp3"
-	const downloadDir = downloadPrefix + musicDir + '/';
-
-	if (!fs.existsSync(downloadDir)){
-		 fs.mkdirSync(downloadDir, true);
+	const extension = audio.file_name.split('.').pop()
+	const performer = cleanString(audio.performer, '.')
+	const title = cleanString(audio.title, '.')
+	var filename = performer + ' - ' + title + '.' + extension
+
+	const dest = downloadPrefix + musicDir + '/' + audio.performer + '/'
+	var data = {
+		file_id: audio.file_id,
+		destination: dest,
+		filename: filename,
+		chat_id: ctx.chat.id
 	}
-	const file = fs.createWriteStream(downloadDir + filename);
-        
-	const promise = telegram.getFile(audio.file_id)	
-	promise.then(function(result){
-		const requestFile = https.get("https://api.telegram.org/file/bot" +
-		process.env.BOT_TOKEN + "/" + result.file_path, function(response) {
-           	if(response.statusCode != 200){
-				return ctx.reply('Error downloading file: ' + response.statuscode)
-			}else{
-				response.pipe(file);
-				console.log('Download finished stored at: ' + downloadDir + filename)
-        			return ctx.reply('Downloaded "' + filename + '"')
-			}
-        	});
-	})
-})
-
-// ----------------------------------------------------------------------------
-
-bot.on('video', (ctx) => {
-	console.log('Video message received from: ', ctx.from.id)
-	telegram.getFile( ctx.message.video.file_id, (ctx) => { 
-		console.log('file_id sent to TG: ', ctx.message.video.file_id)
-	})
-
-	const video = ctx.message.video
-	var filename = video.file_id
-	var extension = '.mp4'
-	if (video.mime_type != undefined){
-		extension = '.' + video.mime_type.split('/')[1]
-	}
-	filename = filename + extension
-	const downloadDir = downloadPrefix + videoDir + '/';
-
-	if (!fs.existsSync(downloadDir)){
-		 fs.mkdirSync(downloadDir, true);
-	}
-	const file = fs.createWriteStream(downloadDir + filename);
-        
-	const promise = telegram.getFile(video.file_id)	
-	promise.then(function(result){
-		const requestFile = https.get("https://api.telegram.org/file/bot" +
-		process.env.BOT_TOKEN + "/" + result.file_path, function(response) {
-           	if(response.statusCode != 200){
-				return ctx.reply('Error downloading file: ' + response.statuscode)
-			}else{
-				response.pipe(file);
-				console.log('Download finished stored at: ' + downloadDir + filename)
-        			return ctx.reply('Downloaded "'+ filename + '"')
-			}
-        	});
-	})
-})
-
-// ----------------------------------------------------------------------------
-
-bot.on('document', (ctx) => {
-	console.log('Document message received from: ', ctx.from.id)
-	telegram.getFile( ctx.message.document.file_id, (ctx) => { 
-		console.log('file_id sent to TG: ', ctx.message.document.file_id)
-	})
-
-	const specialChars = "!@#$^&%*()+=[]\/{}|:<>?, "
-	const document = ctx.message.document
-	var filename = document.file_name
-
-	for (var i = 0; i < specialChars.length; i++) {
-		filename = filename.replace(new RegExp("\\" + specialChars[i], 'gi'), '')
-	}
-
-	const downloadDir = downloadPrefix + documentDir + '/';
-
-	if (!fs.existsSync(downloadDir)){
-		 fs.mkdirSync(downloadDir, true);
-	}
-	const file = fs.createWriteStream(downloadDir + filename);
-        
-	const promise = telegram.getFile(document.file_id)	
-	promise.then(function(result){
-		const requestFile = https.get("https://api.telegram.org/file/bot" +
-		process.env.BOT_TOKEN + "/" + result.file_path, function(response) {
-           	if(response.statusCode != 200){
-				return ctx.reply('Error downloading file: ' + response.statuscode)
-			}else{
-				response.pipe(file);
-				console.log('Download finished stored at: ' + downloadDir + filename)
-        			return ctx.reply('Downloaded "'+ filename + '"')
-			}
-        	});
-	})
+	queue.add(data, options)
+	debug('------------------------------------------------------------')
+	debug('Job added to queue')
+	debug('file_id: %s', data.file_id)
+	debug('destination: %s', data.destination)
+	debug('filename: %s', data.filename)
+	debug('chat_id: %s', data.chat_id)
+	debug('------------------------------------------------------------')
 })
 
 // ----------------------------------------------------------------------------