├── config.json ├── package.json ├── logger.js ├── .gitignore ├── LICENSE ├── README.md └── index.js /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "token": "placeYourTokenHere" 3 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "t-youtube-downloader", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js", 9 | "stop": "pkill -f node" 10 | }, 11 | "author": "“Niklas <“dev@corusm.de”>", 12 | "license": "ISC", 13 | "dependencies": { 14 | "npm": "^6.5.0", 15 | "telegraf": "^3.25.5", 16 | "winston": "^3.1.0", 17 | "youtube-dl": "^1.12.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /logger.js: -------------------------------------------------------------------------------- 1 | // Winston 2 | let winston = require('winston') 3 | let logger = winston.createLogger({ 4 | level: "info", 5 | format: winston.format.combine( 6 | winston.format.timestamp(), 7 | winston.format.printf(info => { 8 | return `${info.timestamp} ${info.level}: ${info.message}`; 9 | }), 10 | ), 11 | transports: [ 12 | new winston.transports.Console(), 13 | new winston.transports.File({filename: 'info.log'}) 14 | ] 15 | }); 16 | 17 | exports.logger = logger; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git 28 | node_modules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Niklas Leinz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Telegram Youtube-Downloader 2 | 3 | This bot sends videos from Youtube to Telegram. I made this bot because when I was in vacations I had a social media flat where I couldn't access Youtube (cruise ship aka. Aida). I just could use messengers like Telegram. 4 | 5 | Because Telegram has a limitation for sending videos the largest possible videos that could be send could have a size of 50MB. Telegram recently made a post where they wrote that they will increase this value soon. 6 | Have fun with this little work around :D 7 | 8 | Important infos: 9 | - Mutltiple users at the same time possible 10 | - Self hosting => Telegram blocks bots that violate the copright 11 | - You can use the bot on your own risk 12 | 13 | # Documentation 14 | 15 | ## Install / Self Hosting 16 | 17 | First install the nodejs and npm packages 18 | ``` 19 | sudo apt-get install nodejs 20 | ``` 21 | ``` 22 | sudo apt-get install npm 23 | ``` 24 | 25 | then clone the git repos to your Server 26 | ``` 27 | git clone https://github.com/corusm/t-youtube-downloader.git 28 | ``` 29 | 30 | ## Install dependencies 31 | ``` 32 | npm install 33 | ``` 34 | 35 | ## Create Bot 36 | Here there are incstructions for creating a Telegram Bot 37 | 1. [Create Telegram Bot](https://www.sohamkamani.com/blog/2016/09/21/making-a-telegram-bot/) 38 | 39 | ## Add Tokens 40 | Add your discord and telegram bot token to the **config.json** file 41 | ``` 42 | { 43 | "telegram": "placeYourTokenHere" 44 | } 45 | ``` 46 | 47 | ## Run the bot 48 | Navigate to the directory where you have installed the bot (where the **index.js** file is located) and run these commands: 49 | 50 | 1. Start Bot: `npm start` 51 | 2. Stop Bot: `npm stop` 52 | 3. Test Bot: `npm test` 53 | 54 | ## Log 55 | All the logs that you see in the shell also get logged in the **info.log** file. 56 | 57 | # Commands 58 | 59 | ## Telegram Command(s): 60 | Let the bot send you the video :D: 61 | * **/video "youtubeVideoID"** 62 | 63 | For searching videos use the bot with the username [@youtube](https://telegram.me/youtube). 64 | 65 | # Help me improving this bot! 66 | If there is any bug to fix or you have a feature request do not hesitate to conctact me! 67 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // Modules 2 | const Telegraf = require('telegraf'); 3 | const fs = require('fs'); 4 | const youtubedl = require('youtube-dl'); 5 | 6 | // Other Files 7 | // Init winston logger (logger.js) 8 | var outplaced = require(`${__dirname}/logger.js`); 9 | var logger = outplaced.logger; 10 | 11 | // Files 12 | const config = require(`${__dirname}/config.json`); 13 | 14 | // Global Vars 15 | var DOWN_URL = "https://www.youtube.com/watch?v="; 16 | var infor; 17 | var TeleMaxData = 50; // 50mb || This mighth change in Future! 18 | var videosize; 19 | 20 | // Bot setup 21 | const bot = new Telegraf(config.token); 22 | logger.log('info', "Bot is running;; TOKEN: " + config.token); 23 | bot.start((ctx) => ctx.reply('Hey there!\nI\'m sending Youtube videos to you!')); 24 | bot.help((ctx) => ctx.reply('Send me a link and I will send you the vid :) \n cmds: \n \n /video {videoID}')); 25 | bot.startPolling(); 26 | 27 | // Catch all errors from bot 28 | bot.catch(function (err) { logger.log('info', err) }); 29 | 30 | // Commands 31 | bot.command('/video', async (ctx) => { 32 | try { 33 | let userID = ctx.from["id"]; 34 | 35 | let input = ctx.message["text"]; 36 | let subText = input.split(" "); 37 | let subSplit; 38 | let videoURL; 39 | 40 | logger.log('info', `-----------NEW_DOWNLOAD_BY_${userID}-----------`); 41 | 42 | if (subText[1].includes("https://youtu.be/")) { 43 | subSplit = subText.split(".be/"); 44 | videoURL = DOWN_URL + subSplit[1] 45 | } else { 46 | videoURL = DOWN_URL + subText[1]; 47 | } 48 | logger.log('info', `Youtube video URL: ${videoURL}`); 49 | 50 | // Remove previous video from cache! 51 | if (fs.existsSync(`${__dirname}/cache/${userID}.mp4`)) { 52 | fs.unlink(`${__dirname}/cache/${userID}.mp4`, (err) => { 53 | if (err) logger.log('info', err); 54 | logger.log('info', `${__dirname}/cache/${userID}.mp4 was deleted`); 55 | }); 56 | } 57 | 58 | // Download video 59 | var video = youtubedl(videoURL, 60 | // Optional arguments passed to youtube-dl. 61 | ['--format=18'], 62 | // Additional options can be given for calling `child_process.execFile()`. 63 | { cwd: __dirname }); 64 | 65 | // Will be called when the download starts. 66 | video.on('info', function (info) { 67 | infor = info; 68 | videosize = infor.size / 1000000; 69 | 70 | if (videosize < TeleMaxData) { 71 | ctx.reply('Download Started') 72 | video.pipe(fs.createWriteStream(`${__dirname}/cache/${userID}.mp4`)); 73 | 74 | // Status of Download 75 | /* UNCOMMENT FOR DOWNLOAD STATUS IN TERMINAL 76 | var pos = 0; 77 | video.on('data', function data(chunk) { 78 | pos += chunk.length; 79 | if (infor.size) { 80 | let percent = (pos / infor.size * 100).toFixed(2); 81 | process.stdout.cursorTo(0); 82 | process.stdout.clearLine(1); 83 | process.stdout.write(percent + '%'); 84 | } 85 | }) 86 | */ 87 | 88 | video.on('end', async function () { 89 | logger.log("info", "Download completed"); 90 | try { 91 | ctx.reply(`Download completed!\nVideo gets Send! - This might take a few Seconds! \n \n Title: \n ${infor.title}. It's ${videosize}mb big.`); 92 | logger.log('info', `Video gets Send! - This might take a few Seconds! \n Title: ${infor.title}, Size: ${videosize}`); 93 | await ctx.replyWithVideo({ 94 | source: fs.createReadStream(`${__dirname}/cache/${userID}.mp4`) 95 | }) 96 | } catch (err) { 97 | logger.log("info", "Error: sendVideo"); 98 | ctx.reply('Error: sendVideo'); 99 | } 100 | }) 101 | } else { 102 | ctx.reply(`The Video is ${videosize}mb. The maximum size for sending videos from Telegram is ${TeleMaxData}mb.`); 103 | logger.log('info', `The Video size is to big! (${videosize}mb)`); 104 | } 105 | }); 106 | } catch (err) { 107 | ctx.reply("ERROR"); 108 | logger.log("info", "error"); 109 | } 110 | }) --------------------------------------------------------------------------------