diff --git a/.spotify b/.spotify new file mode 100644 index 0000000..6e1bd21 Binary files /dev/null and b/.spotify differ diff --git a/.telegram b/.telegram new file mode 100644 index 0000000..a9d415d Binary files /dev/null and b/.telegram differ diff --git a/Data/9.png b/Data/9.png new file mode 100644 index 0000000..a0d9f56 Binary files /dev/null and b/Data/9.png differ diff --git a/Data/header1.png b/Data/header1.png index 9b7d64b..968cc1f 100755 Binary files a/Data/header1.png and b/Data/header1.png differ diff --git a/Procfile b/Procfile index 2c1c45b..c1eeb53 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -worker: python3 telegram.py +worker: bash worker.sh diff --git a/README.md b/README.md index 1e981d5..2469ffd 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,17 @@ -# Spotify Music Downloader | **Get it on Telegram** +# Spotify Music Downloader Bot | **Get it on Telegram** [![made-with-python](https://img.shields.io/badge/Made%20with-Python-1f425f.svg)](https://www.python.org/) [![Open Source Love svg1](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) - - - - - + + + + + + + + + + + + + diff --git a/apple.py b/apple.py index a32de7b..40aedae 100644 --- a/apple.py +++ b/apple.py @@ -16,7 +16,7 @@ def get(self, url): url = url + '&l=uk' - + splitted = str(url).split('/') splitted = splitted[:3]+['ua']+splitted[4:] url = '/'.join(splitted) diff --git a/deezer.py b/deezer.py new file mode 100644 index 0000000..fcdd028 --- /dev/null +++ b/deezer.py @@ -0,0 +1,73 @@ +import requests + +class Deezer(object): + + def __init__(self): + + ''' + Init function + Creating deezer object + :return: None + ''' + + self.__url = 'http://api.deezer.com/' + + + def getSongInfo(self, id): + + try: + + response = requests.get(f'{self.__url}/track/{id}').json() + + return ({ + 'uri' : f"D{response['id']}T", + 'name' : response['title'], + 'artist' : [response['artist']['name']], + 'album' : response['album']['title'], + 'image' : response['album']['cover_xl'], + 'duration_ms' : response['duration'] + }) + + except: return None + + def getAlbum(self, id): + + try: + + response = requests.get(f'{self.__url}/album/{id}').json() + + alb = { + 'name':response['title'], + 'artist':response['artist']['name'], + 'copyright': None, + 'image':response['cover_xl'], + } + + tracks = [] + + for item in response['tracks']['data']: + + tracks.append({ + 'uri' : f"D{item['id']}T", + 'name' : item['title'], + 'artist' : [item['artist']['name']], + 'album' : alb['name'], + 'image' : alb['image'], + 'preview_url' : item['preview'], + 'duration_ms' : item['duration'] + }) + + alb.setdefault( + 'tracks', tracks + ) + + return alb + + except: return None + +if __name__ == '__main__': + + deezer = Deezer() + data = deezer.getSongInfo('636758392') + + print(data) diff --git a/main.py b/main.py index 3c026fa..7c0d9bd 100755 --- a/main.py +++ b/main.py @@ -3,6 +3,7 @@ from youtube import Youtube from editor import TagEditor from lastfm import LastFM +from deezer import Deezer import sys, getopt, shutil import os @@ -22,6 +23,7 @@ def __init__(self): self.__spotify = Spotify() self.__editor = TagEditor() self.__last = LastFM() + self.__deezer = Deezer() def __downloadMusicFromYoutube(self, name, uri, dur): @@ -59,6 +61,9 @@ def getData(self, uri): def getLastFMTags(self, name): return self.__last.get(name) + def getDeezerTags(self, id): + return self.__deezer.getSongInfo(id) + def getYoutubeMusicInfo(self, url): return self.__youtube.getNameFromYoutube(url) @@ -302,9 +307,70 @@ def downloadFromYoutubeMusic(self, url, info): else: return False, None + def downloadByDeezerID(self, uri): + #get info + info = self.__deezer.getSongInfo(uri) + + if info: + + fixed_name = f'{info["artist"][0]} - {info["name"]}' + fixed_name = fixed_name.replace('.','') + fixed_name = fixed_name.replace(',','') + fixed_name = fixed_name.replace("'",'') + fixed_name = fixed_name.replace("/","") + + #finding and download from YouTube and tagging + if self.__downloadMusicFromYoutube(fixed_name, info['uri'], info['duration_ms']): + + self.__editor.setTags( + data=info + ) + + cachepath = os.getcwd() + '/cache' + fullpath = os.getcwd() + '/Downloads' + + #logging + logging.info(f'CACHEPATH {cachepath}') + logging.info(f'FULLPATH {fullpath}') + + if not os.path.exists(fullpath): + os.makedirs(fullpath) + + os.rename( + f"{cachepath}/{info['uri']}/{info['uri']}.png", + f"{fullpath}/{info['uri']}.png" + ) + #logging + logging.info(f"MOVE TO Downloads/{info['uri']}.png") + + os.rename( + f"{cachepath}/{info['uri']}/{info['uri']}.mp3", + f"{fullpath}/{info['uri']}.mp3" + ) + #logging + logging.info(f"MOVE TO Downloads/{info['uri']}.mp3") + + #deleting cache + try: + shutil.rmtree(f"cache/{info['uri']}") + #logging + logging.info(f"DELETED cache/{info['uri']}") + except: + #logging + logging.error(f"DELETING cache/{info['uri']}") + + return True + return False + def search(self, query): return self.__spotify.search(query=query) + def getAlbum(self, uri): + return self.__spotify.getAlbum(uri) + + def getAlbumDeezer(self, id): + return self.__deezer.getAlbum(id) + class CLI(object): diff --git a/requirements.txt b/requirements.txt index bd7110b..3d4c878 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,12 @@ -mutagen==1.41.0 -lxml==4.2.3 -Flask==0.12.2 -moviepy==0.2.3.5 -requests==2.18.4 -spotipy==2.4.4 -git+git://github.com/nficano/pytube.git +redis==2.10.6 imageio==2.3.0 +git+git://github.com/nficano/pytube.git +spotipy==2.4.4 pyperclip==1.6.4 +requests==2.18.4 +moviepy==0.2.3.5 +lxml==4.2.3 +mutagen==1.41.0 +Flask==0.12.2 +celery==4.2.1 beautifulsoup4==4.7.1 diff --git a/spotify.py b/spotify.py index 6e66520..93f182b 100755 --- a/spotify.py +++ b/spotify.py @@ -9,6 +9,7 @@ import webbrowser #flask server from flask import Flask, request +import pickle class Spotify(object): @@ -43,27 +44,27 @@ def code(): class User(object): - def __init__( - self, - client_id = '83e4430b4700434baa21228a9c7d11c5', - client_secret = '9bb9e131ff28424cb6a420afdf41d44a' - ): + def __init__(self): - self.__client_id = client_id - self.__client_secret = client_secret self.__grant_type = 'authorization_code' self.__scope = 'user-library-read' + self.__getData() self.__redirect = 'http://localhost:5000/' self.__urlCode = f'https://accounts.spotify.com/authorize?client_id={self.__client_id}&response_type=code&redirect_uri={self.__redirect}&scope={self.__scope}' self.__url = 'https://accounts.spotify.com/api/token' + self.__getRefreshToken() + self.__client = spotipy.Spotify(auth=self.__access_token) + + + def __getAccessToken(self): + #start server #handling the code webbrowser.open_new(self.__urlCode) Spotify.Server.run() self.__code = Spotify.Server.code - self.__body_params = { 'grant_type': self.__grant_type, 'code': self.__code, @@ -71,16 +72,62 @@ def __init__( } #getting access_token by POST request to Spotify API - self.__access_token = requests.post( + response = requests.post( self.__url, data=self.__body_params, auth=( self.__client_id, self.__client_secret ) - ).json()['access_token'] + ).json() - self.__client = spotipy.Spotify(auth=self.__access_token) + self.__access_token = response['access_token'] + self.__refresh_token = response['refresh_token'] + + data = {'refresh_token' : self.__refresh_token} + + with open('.spotify', 'wb') as f: + pickle.dump(data, f) + + + def __getAccessTokenByRefreshToken(self, refresh_token): + response = requests.post('https://accounts.spotify.com/api/token?', + { + 'grant_type': 'refresh_token', + 'refresh_token': str(refresh_token), + 'client_id': self.__client_id, + 'client_secret': self.__client_secret + } + ).json() + self.__access_token = response['access_token'] + + + def __getRefreshToken(self): + try: + + with open('.spotify', 'rb') as f: + data = pickle.load(f) + self.__getAccessTokenByRefreshToken(data['refresh_token']) + + except: + self.__getAccessToken() + + + def __getData(self): + try: + + with open('.spotify', 'rb') as f: + data = pickle.load(f) + + self.__client_id = data['client_id'] + self.__client_secret = data['client_secret'] + + except: + print(''' + A new version is available on GitHub.\n + Download: https://github.com/artyshko/smd + ''') + sys.exit() def getPlaylistTracks(self, playlist_uri): @@ -110,47 +157,64 @@ def getPlaylistTracks(self, playlist_uri): 'name' : data['name'], 'artist' : [ artist['name'] for artist in data['artists']], 'album' : data['album']['name'], - 'image' : data['album']['images'][0]['url'] + 'image' : data['album']['images'][0]['url'], + 'duration_ms':data['duration_ms'] }) return tracks - def __init__( - self, - client_id = '83e4430b4700434baa21228a9c7d11c5', - client_secret = '9bb9e131ff28424cb6a420afdf41d44a' - ): + def __init__(self): ''' Init function Creating spotify object with access_token - :param client_id: spotify client_id parametr - :param client_secret: spotify client_secret parametr :return: None ''' self.__url = 'https://accounts.spotify.com/api/token' - self.__client_id = client_id - self.__client_secret = client_secret self.__grant_type = 'client_credentials' self.__body_params = { 'grant_type': self.__grant_type } + self.__getData() + self.__getAccessToken() + + #initialization of spotify client + self.client = spotipy.Spotify(self.__access_token) + + + def __getData(self): + try: + + with open('.spotify', 'rb') as f: + data = pickle.load(f) + + self.__client_id = data['client_id'] + self.__client_secret = data['client_secret'] + + except: + print(''' + A new version is available on GitHub.\n + Download: https://github.com/artyshko/smd + ''') + sys.exit() + + + def __getAccessToken(self): #getting access_token by POST request to Spotify API - self.__access_token = requests.post( + response = requests.post( self.__url, data=self.__body_params, auth=( self.__client_id, self.__client_secret ) - ).json()['access_token'] + ).json() - #initialization of spotify client - self.client = spotipy.Spotify(self.__access_token) + self.__access_token = response['access_token'] def getSongInfo(self, uri): @@ -185,7 +249,51 @@ def search(self, query): except: return False + def getDuration(self, uri): data = self.client.track(uri) return data['duration_ms'] + + + def getAlbum(self, uri): + try: + + album = self.client.album(uri) + + copyright = None + + try:copyright = album['copyrights'][0]['text'] + except:pass + + alb = { + 'name':album['name'], + 'artist':album['artists'][0]['name'], + 'copyright':copyright, + 'image':album['images'][0]['url'], + } + + tracks = [] + + for data in album['tracks']['items']: + tracks.append({ + 'uri' : str(data['uri'].split(':')[-1]), + 'name' : data['name'], + 'artist' : [ artist['name'] for artist in data['artists']], + 'album' : alb['name'], + 'image' : alb['image'], + 'preview_url' : data['preview_url'], + 'duration_ms' : data['duration_ms'] + }) + + alb.setdefault( + 'tracks', tracks + ) + + return alb + + except: return None + +if __name__ == '__main__': + s = Spotify() + s.getAlbum('0nW0w37lrQ87k7PLZvC4qJ') diff --git a/telegram.py b/telegram.py index f315079..6d23034 100644 --- a/telegram.py +++ b/telegram.py @@ -1,9 +1,14 @@ +from celery import Celery + import requests import datetime import io, os import re import main import apple +import random +import urllib.request +import pickle import logging @@ -12,13 +17,29 @@ console = logging.StreamHandler() console.setLevel(logging.INFO) +manager = Celery('telegram',broker='redis://smd:mThquQxrJbyVYVlmLLAmwzLd2t5vDWVO@redis-12274.c52.us-east-1-4.ec2.cloud.redislabs.com:12274') class BotHandler(object): def __init__(self): - self.token = '752979930:AAFhdyGx0CSOJ-m17wLGN0NhrxvpwCqCPoQ' + self.__getData() self.api_url = "https://api.telegram.org/bot{}/".format(self.token) + def __getData(self): + try: + + with open('.telegram', 'rb') as f: + data = pickle.load(f) + + self.token = data['token'] + + except: + print(''' + A new version is available on GitHub.\n + Download: https://github.com/artyshko/smd + ''') + sys.exit() + def getUpdates(self, offset=None, timeout=30): method = 'getUpdates' @@ -148,21 +169,69 @@ def __init__(self): self.downloader = main.MusicDownloader() self.apple = apple.AppleMusic() - def classify(self, message): - if str(message).find('open.spotify.com') > 0: - return 'link' + def __restart(self): - elif str(message).find(':track:') > 0: - return 'uri' + #logging + logging.warning(f'Restarting a downloader') + logging.warning(f'Trying to do the same') - elif str(message) == '/start': - return 'start' + self.downloader = main.MusicDownloader() - else: - return 'text' + return True + + def __send(self, data, user, incorrect=False): + + uri, name = data['uri'], getCorrect(f'{data["artist"][0]} - {data["name"]}') + + os.rename( + f"Downloads/{name if incorrect else uri}.mp3", + f"Downloads/{uri if incorrect else name}.mp3" + ) + + return self.bot.sendAudio( + chat_id=user, + audio=open(f"Downloads/{uri if incorrect else name}.mp3",'rb'), + thumb=open(f"Downloads/{uri}.png",'rb'), + name=f'{data["name"]}', + artist=f'{data["artist"][0]}' + ) + + def __remove(self, data, incorrect=False): + + uri, name = data['uri'], getCorrect(f'{data["artist"][0]} - {data["name"]}') + + #deleting song and cover + os.remove(f"Downloads/{uri if incorrect else name}.mp3") + #logging + logging.info(f"DELETED Downloads/{uri if incorrect else name}.mp3") + + os.remove(f"Downloads/{uri}.png") + #logging + logging.info(f'DELETED Downloads/{uri}.png') + + def __sendStatus(self, user): + + self.bot.sendText(user, text='200 ALIVE') + + return True + + def __sendStartMessage(self, user): + + self.bot.sendText( + user, + text='https://telegra.ph/How-to-Spotify-Music-Downloader-Bot-full-instruction-03-09' + ) + + #logging + logging.info('Hello message was sent') - def getTrackFromShazam(self, message): + return True + + def __convertToURI(self, link): + return "spotify:track:" + str(str(link).split('/')[-1]).split('?')[0] + + def __getTrackFromShazam(self, message): slug = str(message).split('/')[-1].split('-') @@ -174,20 +243,22 @@ def getTrackFromShazam(self, message): message = str(message).split(' ') count = 0 + for word in message: - if str(word) == 'by': - count+=1 + count += 1 if str(word) == 'by' else 0 + if count != 1: - try: + try: for word in message: try: + if str(word).lower().find(slug[0]) > -1: title.append(word) slug.pop(0) - else: artist.append(word) + except: artist.append(word) @@ -197,21 +268,270 @@ def getTrackFromShazam(self, message): except:pass return str(song).replace('&','') + else: + new = [] [new.append(word if str(word) != 'by' else '-') for word in message] song = " ".join(new) song = str(song).replace('&','') + return str(song) - def convertToURI(self, link): - return "spotify:track:" + str(str(link).split('/')[-1]).split('?')[0] - def isIncorrect(self, text): - r = re.compile("[а-яА-Я]+") - text = str(text).split(' ') - return True if len([w for w in filter(r.match, text)]) else False + def DL_SPOTIFY_ALBUM(self, message, user): + + + link = str(message).split('?')[0] + uri = str(link).split('/')[-1] + data = self.downloader.getAlbum(uri) + path = f"Downloads/{uri}.png" + + + downloadAlbumImage(data['image'], path) + logging.info(f'Downloaded {path}') + + self.bot.sendPhoto( + chat_id=user, + photo=open(path,'rb'), + text=f'Album {data["name"]} by {data["artist"]}\n\n{data["copyright"]}' + ) + + logging.info(f'Sended {path}') + album = data + count = len(album['tracks']) + + for data, i in zip(album['tracks'], range(count)): + #logging + logging.info(f'S-ALBUM {i+1}/{count} | {data["artist"][0]} - {data["name"]}') + + if self.downloader.downloadBySpotifyUri(data['uri']): + + self.sendSong(data=data, user=user) + + os.remove(path) + #logging + logging.info(f'DELETED {path}') + + return True + + def DL_QUERY(self, message, user): + + state, data = self.downloader.downloadBySearchQuery(message) + + if not state: + + #in case of downloader didn't find a song + #restarting downloader + #and trying to get data + self.__restart() + state, data = self.downloader.downloadBySearchQuery(message) + + + if state: + + return self.sendSong(data=data, user=user) + + else: + + #logging + logging.error(f'SENDED "Couldn\'t find that" MESSAGE') + self.bot.sendSticker(user, sticker=open(f"Data/s3.webp",'rb'),) + self.bot.sendText(user, text='Couldn\'t find that:(') + + return False + + def DL_YOUTUBE_MUSIC(self, message, user): + + self.__restart() + + link = 'http' + str(message).split('http')[-1] + link = ''.join(str(link).split('music.')).split('&')[0] + + name = self.downloader.getYoutubeMusicInfo(link) + tags = self.downloader.getLastFMTags(name) + + #logging + logging.info(f"LINK {link}") + logging.info(f"NAME {name}") + + try: + + state, data = self.downloader.downloadFromYoutubeMusic(url=link, info=tags) + + if state: + + return self.sendSong(data=data, user=user) + + else: + + #logging + logging.warning(f"This video is unavailable.") + self.bot.sendSticker(user, sticker=open(f"Data/s2.webp",'rb')) + self.bot.sendText(user, text='This video is unavailable for me(') + + return False + + except: + + try: + + self.DL_QUERY(message=name, user=user) + + except: + + #logging + logging.warning(f"This video is unavailable.") + self.bot.sendSticker(user, sticker=open(f"Data/s2.webp",'rb'),) + self.bot.sendText(user, text='This video is unavailable for me(') + + return False + + return True + + def DL_DEEZER_ALBUM(self, message, user): + + uri = message + + data = self.downloader.getAlbumDeezer(uri) + path = f"Downloads/{uri}.png" + + + downloadAlbumImage(data['image'], path) + logging.info(f'Downloaded {path}') + + self.bot.sendPhoto( + chat_id=user, + photo=open(path,'rb'), + text=f'Album {data["name"]} by {data["artist"]}' + ) + + logging.info(f'Sended {path}') + album = data + count = len(album['tracks']) + + for data, i in zip(album['tracks'], range(count)): + #logging + logging.info(f'D-ALBUM {i+1}/{count} | {data["artist"][0]} - {data["name"]}') + + if self.downloader.downloadByDeezerID(str(data['uri'][1:-1])): + + self.sendSong(data=data, user=user) + + os.remove(path) + #logging + logging.info(f'DELETED {path}') + + return True + + + def sendSong(self, data, user): + + try: + + code = self.__send(data, user=user) + + if int(code) != 200: + + #trying to fix incorrect name + code = self.__send(data, user=user, incorrect=True) + + if int(code) != 200: + + #sending sad message + self.bot.sendText(user, text='Something went wrong:(') + self.__remove(data, incorrect=True) + + return False + + self.__remove(data, incorrect=True) + + return True + + else: + + self.__remove(data) + return True + + except: + + logging.error(f'ERROR IN controller.sendSong()') + self.bot.sendText(user, text='Something went wrong:(') + + return False + + def worker(self,update): + + if 'message' in list(update.keys()): + #in case of new message + + #get message data + chat_id = update['message']['chat']['id'] + + try: + username = update['message']['chat']['username'] + except: + username = 'unknown' + + if 'text' in list(update['message'].keys()): + #skipping unsupported messages + #get message + message = update['message']['text'] + + #logging + logging.info(f'USER [{username}]') + logging.info(f'MESSAGE {message}') + + try: + + #start controller + self.controller(message, chat_id) + + except: + #logging + logging.error('ERROR IN CONTROLLER') + + try: + + self.downloader = main.MusicDownloader() + #restart controller + self.controller(message, chat_id) + + except: + + self.bot.sendSticker(chat_id, sticker=open(f"Data/s1.webp",'rb')) + self.bot.sendText(chat_id, 'Couldn\'t find that :(') + + else: + #logging + logging.warning('UNSUPPORTED MESSAGE') + + self.bot.sendSticker(chat_id, sticker=open(f"Data/s4.webp",'rb')) + self.bot.sendText(chat_id, 'Wooops! Something went wrong.\nERROR CODE 42 - You are so funny!') + + def classify(self, message): + + if str(message).find('open.spotify.com') > 0: + return 'link' + + elif str(message).find(':track:') > 0: + return 'uri' + + elif str(message) == '/start' or str(message) == '/help': + return 'start' + + elif str(message) == '/status': + return 'status' + + elif str(message).find('deezer.com/track/') > 0: + return 'dtrack' + + elif str(message).find('deezer.com/album/') > 0: + return 'dalbum' + + else: + return 'text' def controller(self, message, id): @@ -223,39 +543,28 @@ def controller(self, message, id): #start message if type == 'start': - #logging - logging.info('Sended hello message') - - self.bot.sendPhoto( - chat_id=id, - photo=open(f"Data/header1.png",'rb'), - text='' - ) - self.bot.sendPhoto( - chat_id=id, - photo=open(f"Data/header3.png",'rb'), - text='' - ) - self.bot.sendPhoto( - chat_id=id, - photo=open(f"Data/header5.png",'rb'), - text='' - ) + self.__sendStartMessage(user=id) return True + elif type == 'status': + + self.bot.sendText(id, text='200 ALIVE') + return True elif type == 'text': if str(message).find('I used Shazam to discover') > -1: + #logging logging.info(f"SHAZAM SONG DETECTED") - message = self.getTrackFromShazam(message) + message = self.__getTrackFromShazam(message) logging.info(f"NAME {message}") elif str(message).find('Мое открытие на Shazam:') > -1: + #fix for russian lang new = str(message).split('Мое открытие на Shazam: ')[1] new = str(new).split('. https')[0] @@ -264,6 +573,7 @@ def controller(self, message, id): logging.info(f"NAME {message}") elif str(message).find('youtube.com/watch') > -1: + #logging logging.info(f"YOUTUBE MUSIC DETECTED") @@ -271,158 +581,98 @@ def controller(self, message, id): if str(message).find('music.') > -1: - self.downloader = main.MusicDownloader() - - link = ''.join(str(link).split('music.')).split('&')[0] - - #logging - logging.info(f"LINK {link}") + self.DL_YOUTUBE_MUSIC(message, id) - name = self.downloader.getYoutubeMusicInfo(link) - tags = self.downloader.getLastFMTags(name) + else: #logging - logging.info(f"NAME {name}") - - try: - state, data = self.downloader.downloadFromYoutubeMusic(url=link, info=tags) - - if state: - - code = self.bot.sendAudio( - chat_id=id, - audio=open(f"Downloads/{data['uri']}.mp3",'rb'), - thumb=open(f"Downloads/{data['uri']}.png",'rb'), - name=f'{data["name"]}', - artist=f'{data["artist"][0]}' - ) - - if int(code) != 200: - #logging - logging.warning(f'CODE {code}') - self.bot.sendText(id,text='Something went wrong:(') - - - os.remove(f"Downloads/{data['uri']}.mp3") - #logging - logging.info(f"DELETED Downloads/{data['uri']}.mp3") - - os.remove(f"Downloads/{data['uri']}.png") - #logging - logging.info(f"DELETED Downloads/{data['uri']}.png") - - - else: - #logging - logging.warning(f"This video is unavailable.") - self.bot.sendSticker(id,sticker=open(f"Data/s2.webp",'rb'),) - self.bot.sendText(id,text='This video is unavailable for me(') - - return False - - except: - try: - self.controller(name, id) - except: - #logging - logging.warning(f"This video is unavailable.") - self.bot.sendSticker(id,sticker=open(f"Data/s2.webp",'rb'),) - self.bot.sendText(id,text='This video is unavailable for me(') - - return False - - return True - - else: logging.warning(f"YOUTUBE SONG DETECTED") self.bot.sendSticker(id,sticker=open(f"Data/s5.webp",'rb'),) self.bot.sendText(id,text='You need to use YouTube Music instead of YouTube.') + return False + return True elif str(message).find('youtu.be') > -1: + logging.warning(f"YOUTUBE SONG DETECTED") self.bot.sendSticker(id,sticker=open(f"Data/s5.webp",'rb'),) self.bot.sendText(id,text='You need to use YouTube Music instead of YouTube.') + return True elif str(message).find('itunes.apple.com') > 1: name = self.apple.getName(message) message = name + if not name: + #logging logging.error(f'SENDED "Couldn\'t find that" MESSAGE') self.bot.sendSticker(id,sticker=open(f"Data/s3.webp",'rb'),) self.bot.sendText(id,text='Couldn\'t find that:(') - return False - - state, data = self.downloader.downloadBySearchQuery(message) - - #FIX - if not state: - #logging - self.downloader = main.MusicDownloader() - logging.warning(f'Restarting downloader') - logging.warning(f'Trying do the same') - - state, data = self.downloader.downloadBySearchQuery(message) + return False - if state: + return self.DL_QUERY(message, user=id) - fixed_name = f'{data["artist"][0]} - {data["name"]}' - fixed_name = data['uri'] + elif type == 'dtrack': - code = self.bot.sendAudio( - chat_id=id, - audio=open(f"Downloads/{data['uri']}.mp3",'rb'), - thumb=open(f"Downloads/{data['uri']}.png",'rb'), - name=f'{data["name"]}', - artist=f'{data["artist"][0]}' - ) + #logging + logging.info(f'DEEZER TRACK DETECTED') - if int(code) != 200: - #logging - logging.warning(f'CODE {code}') - self.bot.sendText(id,text='Something went wrong:(') + track = str(str(message).split('/track/')[1]).split('?')[0] + data = self.downloader.getDeezerTags(track) + if data: - os.remove(f"Downloads/{data['uri']}.mp3") #logging - logging.info(f"DELETED Downloads/{data['uri']}.mp3") + logging.info(f'SONG {data["artist"][0]} - {data["name"]}') - os.remove(f"Downloads/{data['uri']}.png") - #logging - logging.info(f"DELETED Downloads/{data['uri']}.png") + if self.downloader.downloadByDeezerID(track): + return self.sendSong(data=data, user=id) else: + #logging - logging.error(f'SENDED "Couldn\'t find that" MESSAGE') + logging.error(f'SENDED "Something went wrong" MESSAGE') self.bot.sendSticker(id,sticker=open(f"Data/s3.webp",'rb'),) self.bot.sendText(id,text='Couldn\'t find that:(') + return False - return True + elif type == 'dalbum': + + #logging + logging.info(f'DEEZER ALBUM DETECTED') + album = str(str(message).split('album/')[1]).split('?')[0] + + return self.DL_DEEZER_ALBUM(album, id) elif type == 'link': #logging - logging.info(f'Converted open.spotify.com link to spotify URI') + logging.info(f'Converting open.spotify.com link to spotify URI') - message = self.convertToURI(message) + if str(message).find('/album/') > -1: + logging.info('ALBUM MODE') + return self.DL_SPOTIFY_ALBUM(message, user=id) - #get data - uri = str(message).split(':')[-1] + message = self.__convertToURI(message) + + #getting data data = self.downloader.getData(message) if not data: - #logging - logging.warning(f'Restarting downloader') - logging.warning(f'Trying do the same') - self.downloader = main.MusicDownloader() + + #in case of downloader didn't find a song + #restarting downloader + #and trying to get data + self.__restart() data = self.downloader.getData(message) if data: @@ -432,32 +682,7 @@ def controller(self, message, id): if self.downloader.downloadBySpotifyUri(message): - - code = self.bot.sendAudio( - chat_id=id, - audio=open(f"Downloads/{uri}.mp3",'rb'), - thumb=open(f"Downloads/{uri}.png",'rb'), - name=f'{data["name"]}', - artist=f'{data["artist"][0]}' - ) - - - if int(code) != 200: - #logging - logging.warning(f'CODE {code}') - self.bot.sendSticker(id,sticker=open(f"Data/s3.webp",'rb'),) - self.bot.sendText(id,text='Something went wrong:(') - - - os.remove(f"Downloads/{uri}.mp3") - #logging - logging.info(f'DELETED Downloads/{uri}.mp3') - - os.remove(f"Downloads/{uri}.png") - #logging - logging.info(f'DELETED Downloads/{uri}.png') - - return True + return self.sendSong(data=data, user=id) else: @@ -465,73 +690,56 @@ def controller(self, message, id): logging.error(f'SENDED "Something went wrong" MESSAGE') self.bot.sendSticker(id,sticker=open(f"Data/s3.webp",'rb'),) self.bot.sendText(id,text='Couldn\'t find that:(') - return False - - - def mainloop(self): - while True: - - self.bot.getUpdates(self.offset) - update = self.bot.checkLastUpdates() - - if update: - - update_id = update['update_id'] - - if 'message' in list(update.keys()): - #in case of new message - - #get message data - chat_id = update['message']['chat']['id'] - - try: - username = update['message']['chat']['username'] - except: - username = 'unknown' + return False - if 'text' in list(update['message'].keys()): - #skipping unsupported messages - #get message - message = update['message']['text'] - #logging - logging.info(f'USER [{username}]') - logging.info(f'MESSAGE {message}') +def getCorrect(name): + try: + #checking out incorrect words + r, text = re.compile("[а-яА-Я]+"), str(name).split(' ') + status = True if len([w for w in filter(r.match, name)]) else False - try: + if status: + return f'S{str(random.randint(1000000000,100000000000))}D' - #start controller - self.controller(message, chat_id) + return re.sub(r"[\"#/@;:<>{}`+=~|.!?$%^&*№&]", string=name, repl='') - except: - #logging - logging.error('ERROR IN CONTROLLER') + except: - try: + return 'music' - self.downloader = main.MusicDownloader() - #restart controller - self.controller(message, chat_id) +def downloadAlbumImage(url, name): + urllib.request.urlretrieve(url, name) - except: +@manager.task +def do(update): + controller = Controller() + controller.worker(update) + del controller - self.bot.sendSticker(chat_id, sticker=open(f"Data/s1.webp",'rb')) - self.bot.sendText(chat_id, 'Couldn\'t find that :(') +def mainloop(): - else: - #logging - logging.warning('UNSUPPORTED MESSAGE') + offset = None + bot = BotHandler() - self.bot.sendSticker(chat_id, sticker=open(f"Data/s4.webp",'rb')) - self.bot.sendText(chat_id, 'Wooops! Something went wrong.\nERROR CODE 42 - You are so funny!') + while True: + try: - self.offset = update_id + 1 + bot.getUpdates(offset) + update = bot.checkLastUpdates() + if update: + update_id = update['update_id'] + offset = update_id + 1 + #celery task + do.delay(update) + except: + offset = None + bot = BotHandler() if __name__ == '__main__': logging.info('Starting app') - controller = Controller() - controller.mainloop() + mainloop() diff --git a/worker.sh b/worker.sh new file mode 100644 index 0000000..cd9884f --- /dev/null +++ b/worker.sh @@ -0,0 +1 @@ +python3 telegram.py & celery worker -A telegram --loglevel=info --autoscale=5,2 diff --git a/youtube.py b/youtube.py index b036156..1c094cb 100755 --- a/youtube.py +++ b/youtube.py @@ -150,7 +150,7 @@ def convertVideoToMusic(self, uri): try: clip = mp.VideoFileClip(f'cache/{uri}/{uri}.mp4').subclip() - clip.audio.write_audiofile(f'cache/{uri}/{uri}.mp3', bitrate='3000k') + clip.audio.write_audiofile(f'cache/{uri}/{uri}.mp3', bitrate='3000k', progress_bar=False) logging.info(f"Converting successful")