diff --git a/Dockerfile b/Dockerfile index f72ee88..06dbc9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,13 +11,12 @@ RUN pip3 install youtube-dl RUN pip3 install boto3 RUN apt-get install -qqy locales - RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ locale-gen ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 -CMD ["python3", "/src/bin/consumerSQS/main.py"] +CMD ["python3", "/src/bin/main.py"] diff --git a/consumerSQS/config.py.template b/config.py.template similarity index 58% rename from consumerSQS/config.py.template rename to config.py.template index ed60f00..5a4c879 100644 --- a/consumerSQS/config.py.template +++ b/config.py.template @@ -3,4 +3,7 @@ config = { "access_key" : "", "secret_access_key" : "", "library_path": "" + "region_name":"", + "endpoint_url":"", + "QueueName":"" } diff --git a/consumerSQS/answer.py b/consumerSQS/answer.py deleted file mode 100644 index 1b5b664..0000000 --- a/consumerSQS/answer.py +++ /dev/null @@ -1,12 +0,0 @@ -import subprocess -from config import config -from string import Template -import logging - -def send_message(txt,userId): - curlCommand = Template ("curl -X POST -H \"Content-Type: application/json\" -d '{ \"recipient\": { \"id\": \"$userId\" },\"message\": { \"text\": \"$msg\" }}' \"https://graph.facebook.com/v2.6/me/messages?access_token=$token\" ") - request=curlCommand.substitute(userId=userId,msg=txt,token=config["tokenFacebook"]) - logging.debug(request) - print(request) - subprocess.check_call(request,shell=True,stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT) - diff --git a/consumerSQS/consumer.py b/consumerSQS/consumer.py deleted file mode 100644 index 249b747..0000000 --- a/consumerSQS/consumer.py +++ /dev/null @@ -1,43 +0,0 @@ -import boto3 -import logging -from config import config -import answer -import json -import time -import librarian -import messageGoogle -import messageFacebook - - -def work(message): - return sendToManager(message) - -def sendToManager(message): - logging.debug("Manager received:"+str(message)) - - if type(message) == messageFacebook.MessageFacebook : - um = librarian.User_manager(message.get_sender_id()) - try: - um.user_event("MESSAGE",message.get_text()) - except Exception as e: - print(e) - um.user_event("MESSAGE",message.get_url()) - else: - um = librarian.User_manager(message.get_sender_id()) - um.user_event("IDENTIFICATION",message.get_code()) - return True - -def parrot_work(message): - try : - msgToSend = "I ear your request :"+str(message["entry"][0]["messaging"][0]["message"]["text"]) - idReceiver = message["entry"][0]["messaging"][0]["sender"]["id"] - print (idReceiver+":"+msgToSend) - answer.send_message(msgToSend,idReceiver) - answer.send_message("I will",idReceiver) - return True - except Exception as e: - print(e) - return False - - - diff --git a/consumerSQS/librarian.py b/consumerSQS/librarian.py deleted file mode 100644 index f0ec316..0000000 --- a/consumerSQS/librarian.py +++ /dev/null @@ -1,183 +0,0 @@ -from oauth2client.client import OAuth2WebServerFlow, TokenRevokeError -import oauth2client.file -from config import config -import os -from gmusicapi import Musicmanager -import subprocess -import sys -import glob -import os -from time import sleep -import httplib2 -from collections import namedtuple -import answer -import urllib -import pickle -import re -import time -import logging -import traceback -import youtube_dl - -OAuthInfo = namedtuple('OAuthInfo', 'client_id client_secret scope redirect') -oauth = OAuthInfo( - '794418103801-69gbuc7jmlnitpflnmbjqdq3bgimecji.apps.googleusercontent.com', - '-_6HrNIO-zDO6a0fSm_drOkR', - 'https://www.googleapis.com/auth/musicmanager', - 'https://phagekwmf7.execute-api.us-west-2.amazonaws.com/Prod/identification' -) - -ydl_opts_download = { - 'format': 'bestaudio/best', - 'postprocessors': [{'key': 'FFmpegMetadata'}, - { - 'key': 'FFmpegExtractAudio', - 'preferredcodec': 'mp3', - }], - 'addmetadata':True, - 'verbose':True, -} -ydl_opts_title = { - 'simulate':True, -} - -class User_state(): - def __init__(self,userId): - self.userId = userId - self.state = None - self.queue = [] - self.metadataState = None - self.count = 0 - self.creationTimestamp = time.time() - self.lastInteractionTimestamp = time.time() - -class User_manager(): - - isTinyURL = False - userId = None - user_state = None - folder_path = None - def __init__(self,userId): - self.userId = userId - self.folder_path = config["library_path"]+str(userId)+"/" - ydl_opts_download["outtmpl"]= self.folder_path+"%(title)s.%(ext)s" - try: - os.mkdir(self.folder_path) - self.user_state = User_state(userId) - except Exception as e: - try: - self.user_state = self.reconstruct_user_state(self.userId) - except Exception as e: - logging.warning("USER NOT FOUND, SHOULD NOT HAPPEN, reinit of all data") - self.user_state = User_state(userId) - - def build_user_file(self,user_state): - user_state.lastInteractionTimestamp = time.time() - pickle.dump(user_state, open(self.folder_path+"state.p","wb")) - return True - - def reconstruct_user_state(self,userId): - user_state = pickle.load(open(self.folder_path+"state.p", 'rb')) - if not hasattr(user_state, 'count'): - user_state.count = 0 - return user_state - - def user_event(self,event,payload): - logging.debug(self.userId+"| "+str(event)+"|"+str(payload)) - if "reset" in payload : - self.user_state.state = None - self.build_user_file(self.user_state) - try: - if self.user_state.state is None and "MESSAGE" in event: - self.ask_credentials() - self.user_state.state = "CREDENTIALS WAITING" - elif "CREDENTIALS WAITING" in self.user_state.state and "IDENTIFICATION" in event : - self.verify_credentials(payload) - answer.send_message("Hey everything is setup !",self.userId) - self.user_state.state = "SET UP COMPLETED" - elif "SET UP COMPLETED" in self.user_state.state : - if not self.is_a_correct_url(payload): - answer.send_message("Hum, I dont understand",self.userId) - else : - logging.info("Url understood") - self.process_url(payload) - self.user_state.count += 1 - answer.send_message("Hey niceJob !!",self.userId) - self.build_user_file(self.user_state) - except Exception as e: - logging.error(e) - logging.error(traceback.format_exc()) - answer.send_message("Outch !",self.userId) - answer.send_message("Something gone wrong",self.userId) - answer.send_message("I will keep you informed",self.userId) - - def is_a_correct_url(self,url): - if "l.facebook.com" in url: - fb_redirection = subprocess.check_output(["curl",url]) - p = re.compile('watch\?v=(.{11})\"') - uid = p.search(fb_redirection.decode('ascii')).group(1) - else: - uid= url - try: - info = youtube_dl.YoutubeDL(ydl_opts_title).extract_info(uid) - if info["duration"] < 600 : - return True - return False - except youtube_dl.DownloadError as e: - return False - - def process_url(self, url): - if "l.facebook.com" in url: - fb_redirection = subprocess.check_output(["curl",url]) - p = re.compile('watch\?v=(.{11})\"') - uid = p.search(fb_redirection.decode('ascii')).group(1) - else: - uid= url - youtube_dl.YoutubeDL(ydl_opts_download).download([uid]) - files=glob.glob(self.folder_path+"/*.mp3") - for music in files: - try: - mm=Musicmanager() - mm.login(oauth_credentials = self.folder_path+"oauth.cred", uploader_id='02:42:3D:5B:ED:7B') - code=mm.upload(music) - logging.info("value return after upload by gmusic") - if len(code[0])==1: - try: - os.remove(music) - except OSError: - pass - except TypeError as e: - logging.error(e) - try: - mm.login() - except gmusicapi.exceptions.AlreadyLoggedIn as e: - pass - - def ask_credentials(self): - self.user_state.flow = OAuth2WebServerFlow(*oauth) - auth_uri = self.user_state.flow.step1_get_authorize_url()+"&state="+str(self.userId+"&prompt=consent") - answer.send_message("Please follow the link and paste the code back to me !",self.userId) - try: - if self.isTinyURL: - self.ask_tiny_url(auth_uri) - except Exception as e: - self.isTinyURL = False - if not self.isTinyURL: - self.ask_auth_uri(auth_uri) - - return - def verify_credentials(self,code): - credentials = self.user_state.flow.step2_exchange(code) - storage = oauth2client.file.Storage(self.folder_path+"oauth.cred") - storage.put(credentials) - time.sleep(20) - mm=Musicmanager() - mm.login(oauth_credentials = self.folder_path+"oauth.cred",uploader_id='3c:f8:62:67:01:0b') - - def ask_auth_uri(self, auth_uri): - answer.send_message(auth_uri,self.userId) - - def ask_tiny_url(self,tiny_url): - tiny_url = subprocess.check_output(["curl","http://tinyurl.com/api-create.php?url="+str(auth_uri)+ "'"]) - answer.send_message(tiny_url.decode("utf-8"),self.userId) - answer.send_message("Psst, its a tiny URL, dont freakout, its Google behind",self.userId) diff --git a/consumerSQS/main.py b/consumerSQS/main.py deleted file mode 100644 index fbdfb76..0000000 --- a/consumerSQS/main.py +++ /dev/null @@ -1,65 +0,0 @@ -import boto3 -import logging -from config import config -import answer -import json -import time -import librarian -import consumer -import messageFacebook -import messageGoogle -from enum import Enum -import os -from config import config -import sys -import traceback - -class Source(Enum): - GOOGLE = 1 - FACEBOOK = 2 - -def isPayloadFrom(payload): - if type(payload) == str : - payload = json.loads(payload) - if type(payload) == str : - payload = json.loads(payload) - try : - sender_id = payload["entry"][0]["messaging"][0]["sender"]["id"] - return Source.FACEBOOK - except KeyError as e: - return Source.GOOGLE - - -if not os.path.exists(config["library_path"]): - logging.critical("Library folder doesn't exist") - sys.exit("Library folder doesn't exist") - - - -logging.info("Service starting") -sqs = boto3.resource('sqs',aws_access_key_id = config["access_key"], aws_secret_access_key=config["secret_access_key"], region_name="us-west-2", endpoint_url="https://sqs.us-west-2.amazonaws.com/731910755973/MessagesYouMus.fifo") -logging.info("sqs succesfully accessed") -logging.info("Waiting for message") -while True: - queue = sqs.get_queue_by_name(QueueName='MessagesYouMus.fifo') - for msg in queue.receive_messages(): - logging.getLogger().setLevel(level=logging.INFO) - logging.debug("Received ="+str(msg.body)) - source = isPayloadFrom(msg.body) - try: - if source == Source.FACEBOOK : - msg_wrapper = messageFacebook.MessageFacebook(msg.body) - msg.delete() - status = consumer.work(msg_wrapper) - elif source == Source.GOOGLE : - msg_wrapper = messageGoogle.MessageGoogle(msg.body) - msg.delete() - status = consumer.work(msg_wrapper) - else: - pass - except Exception as e: - logging.error(e) - logging.error(traceback.format_exc()) - logging.error("Show must go on\n") - logging.getLogger().setLevel(level=logging.ERROR) - time.sleep(0.2) diff --git a/consumerSQS/message.py b/consumerSQS/message.py deleted file mode 100644 index 17efead..0000000 --- a/consumerSQS/message.py +++ /dev/null @@ -1,3 +0,0 @@ - -class Message (): - pass \ No newline at end of file diff --git a/consumerSQS/messageFacebook.py b/consumerSQS/messageFacebook.py deleted file mode 100644 index 4447f77..0000000 --- a/consumerSQS/messageFacebook.py +++ /dev/null @@ -1,29 +0,0 @@ -import json -import re -import message - -class MessageFacebook(message.Message): - def __init__(self,body): - self.body = json.loads(body) - if type(self.body) == str : - self.body = json.loads(self.body) - if type(self.body)==str : - self.body = json.loads(self.body) - def get_sender_id(self): - sender_id = self.body["entry"][0]["messaging"][0]["sender"]["id"] - return sender_id - - def get_text(self): - text = self.body["entry"][0]["messaging"][0]["message"]["text"] - return text - def get_url(self): - url = "" - try : - url = self.body["entry"][0]["messaging"][0]["message"]["attachments"][0]["url"] - except Exception as e: - urls = re.findall('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', self.get_text()) - if len(urls) > 0: - url = urls[0] - if len(url)<1: - raise AttributeError - return url \ No newline at end of file diff --git a/fifo_parser/__init__.py b/fifo_parser/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fifo_parser/facebookmessage.py b/fifo_parser/facebookmessage.py new file mode 100644 index 0000000..27dfb96 --- /dev/null +++ b/fifo_parser/facebookmessage.py @@ -0,0 +1,24 @@ +import json + + +class FacebookMessage: + def __init__(self, body): + self.body = json.loads(body) + if type(self.body) == str: + self.body = json.loads(self.body) + if type(self.body) == str: + self.body = json.loads(self.body) + + def get_sender_id(self): + sender_id = self.body["entry"][0]["messaging"][0]["sender"]["id"] + return sender_id + + def get_text(self): + text = self.body["entry"][0]["messaging"][0]["message"]["text"] + return text + + def get_url(self): + url = "" + if len(url) < 1: + raise AttributeError + return url diff --git a/consumerSQS/messageGoogle.py b/fifo_parser/googlemessage.py similarity index 58% rename from consumerSQS/messageGoogle.py rename to fifo_parser/googlemessage.py index 46321a7..613c415 100644 --- a/consumerSQS/messageGoogle.py +++ b/fifo_parser/googlemessage.py @@ -1,18 +1,19 @@ import json -import re -import message -class MessageGoogle(message.Message): - def __init__(self,body): + +class GoogleMessage: + def __init__(self, body): self.body = json.loads(body) - if type(self.body) == str : + if type(self.body) == str: self.body = json.loads(self.body) - if type(self.body)==str : + if type(self.body) == str: self.body = json.loads(self.body) - + def get_sender_id(self): return self.body["state"] + + def get_text(self): + return self.body + def get_code(self): return self.body["code"] - - \ No newline at end of file diff --git a/fifo_parser/messageexecutor.py b/fifo_parser/messageexecutor.py new file mode 100644 index 0000000..d163c99 --- /dev/null +++ b/fifo_parser/messageexecutor.py @@ -0,0 +1,34 @@ +import logging +import time + +from fifo_parser.facebookmessage import FacebookMessage +from fifo_parser.messageslistener import MessagesListener +from users_push.usermanager import UserManager + + +class MessageExecutor: + + def __init__(self): + self.msg_listener = MessagesListener() + self.user_manager = UserManager() + self.user_manager.init_users() + + def run(self): + while True: + wrapped_message = self.msg_listener.receive_messages() + if wrapped_message is None: + pass + else: + self.execute_message(wrapped_message) + time.sleep(0.2) + + def execute_message(self, message): + logging.info("Execute:"+str(message.body)) + if self.user_manager.is_new_user(message.get_sender_id()): + self.user_manager.create_user(message.get_sender_id()) + + if type(message) == FacebookMessage: + self.user_manager.user_event("MESSAGE", message) + else: + self.user_manager.user_event("IDENTIFICATION", message) + return True diff --git a/fifo_parser/messageslistener.py b/fifo_parser/messageslistener.py new file mode 100644 index 0000000..aa15770 --- /dev/null +++ b/fifo_parser/messageslistener.py @@ -0,0 +1,59 @@ +import json +import logging +from enum import Enum + +import boto3 as boto3 + +from config import config +from fifo_parser.facebookmessage import FacebookMessage +from fifo_parser.googlemessage import GoogleMessage + + +class Source(Enum): + GOOGLE = 1 + FACEBOOK = 2 + + +def is_payload_from(payload): + if type(payload) == str: + payload = json.loads(payload) + if type(payload) == str: + payload = json.loads(payload) + try: + sender_id = payload["entry"][0]["messaging"][0]["sender"]["id"] + return Source.FACEBOOK + except KeyError as e: + return Source.GOOGLE + + +class MessagesListener: + sqs = None + + def __init__(self): + logging.info("Service starting") + self.sqs = boto3.resource('sqs', aws_access_key_id=config["access_key"], + aws_secret_access_key=config["secret_access_key"], region_name=config["region_name"], + endpoint_url=config["endpoint_url"]) + self.queue = self.sqs.get_queue_by_name(QueueName=config["QueueName"]) + logging.info("sqs successfully accessed") + + def receive_messages(self): + logging.info("Waiting for message") + logging.getLogger().setLevel(level=logging.ERROR) + for msg in self.queue.receive_messages(): + logging.getLogger().setLevel(level=logging.INFO) + logging.info("Received =" + str(msg.body)) + msg.delete() + return MessagesListener.wrap_raw_msg(msg) + + @staticmethod + def wrap_raw_msg(msg): + source = is_payload_from(msg.body) + if source == Source.FACEBOOK: + msg_wrapper = FacebookMessage(msg.body) + return msg_wrapper + elif source == Source.GOOGLE: + msg_wrapper = GoogleMessage(msg.body) + return msg_wrapper + else: + raise NotImplementedError diff --git a/library/1588048767881420/oauth.cred b/library/1588048767881420/oauth.cred new file mode 100644 index 0000000..4c43d3c --- /dev/null +++ b/library/1588048767881420/oauth.cred @@ -0,0 +1 @@ +{"scopes": ["https://www.googleapis.com/auth/musicmanager"], "_module": "oauth2client.client", "refresh_token": "1/ov3G1GAnUDAFOQowpCUdntc5Cxztsd4T-uhNZ1XyW7_6u5HQxpaEI_9LUbiEV62k", "client_id": "794418103801-69gbuc7jmlnitpflnmbjqdq3bgimecji.apps.googleusercontent.com", "token_info_uri": "https://oauth2.googleapis.com/tokeninfo", "_class": "OAuth2Credentials", "client_secret": "-_6HrNIO-zDO6a0fSm_drOkR", "invalid": false, "token_response": {"token_type": "Bearer", "expires_in": 3600, "access_token": "ya29.GlsaBibo4DOFv1yfniiNEhfWQH_vz_d2qRB4AcNc0daSWB-EFEb29w0Hgl6MrIpkD7d5cDa1i0VxKgow583Bimk8jERJ59u31KVO0TTY3n_jEI6kwAaSmoeDtCS6", "scope": "https://www.googleapis.com/auth/musicmanager"}, "access_token": "ya29.GlsaBibo4DOFv1yfniiNEhfWQH_vz_d2qRB4AcNc0daSWB-EFEb29w0Hgl6MrIpkD7d5cDa1i0VxKgow583Bimk8jERJ59u31KVO0TTY3n_jEI6kwAaSmoeDtCS6", "id_token": null, "token_uri": "https://oauth2.googleapis.com/token", "token_expiry": "2018-09-16T17:44:36Z", "user_agent": null, "revoke_uri": "https://oauth2.googleapis.com/revoke", "id_token_jwt": null} \ No newline at end of file diff --git a/library/1588048767881420/state.p b/library/1588048767881420/state.p new file mode 100644 index 0000000..0f63e62 Binary files /dev/null and b/library/1588048767881420/state.p differ diff --git a/main.py b/main.py new file mode 100644 index 0000000..1a75e55 --- /dev/null +++ b/main.py @@ -0,0 +1,23 @@ + +import logging +import fifo_parser.messageexecutor + +# create logger +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +ch = logging.StreamHandler() +ch.setLevel(logging.INFO) + +# create formatter +formatter = logging.Formatter("%(asctime)s;%(levelname)s;%(message)s", + "%Y-%m-%d %H:%M:%S") + +# add formatter to ch +ch.setFormatter(formatter) + +# add ch to logger +logger.addHandler(ch) + +me = fifo_parser.messageexecutor.MessageExecutor() +me.run() diff --git a/media/__init__.py b/media/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/media/downloader.py b/media/downloader.py new file mode 100644 index 0000000..bd1e165 --- /dev/null +++ b/media/downloader.py @@ -0,0 +1,100 @@ +import glob +import re +import subprocess +from config import config +import youtube_dl as youtube_dl + +ydl_opts_download = { + 'format': 'bestaudio/best', + 'postprocessors': [{'key': 'FFmpegMetadata'}, + { + 'key': 'FFmpegExtractAudio', + 'preferredcodec': 'mp3', + }], + 'addmetadata': True, + 'quiet': True, + 'verbose': False, +} +ydl_opts_title = { + 'quiet': True, + 'simulate': True, +} + + +class Downloader: + + def is_a_correct_url(self, url): + if "l.facebook.com" in url: + fb_redirection = subprocess.check_output(["curl", url]) + p = re.compile('watch\?v=(.{11})\"') + uid = p.search(fb_redirection.decode('ascii')).group(1) + else: + uid = url + try: + info = youtube_dl.YoutubeDL(ydl_opts_title).extract_info(uid) + if "_type" in info and info["_type"] == "playlist": + for music in info['entries']: + if music["duration"] > 600: + return False + return True + elif info["duration"] < 600: + return True + return False + # Triggered by "Hey niceJob !!https://www.youtube.com/playlist?list=PL3aW5sLM3-BtUIYjBhCgHCVSagK6R3LWi" + except ValueError: + return False + except youtube_dl.DownloadError: + return False + except KeyError: + return False + + def add_metadata(self, path, artist): + subprocess.check_call( + ["ffmpeg", "-v", "warning", "-y", "-i", str(path), "-c", "copy", "-metadata", "artist=" + str(artist), + str(path) + "bis.mp3"]) + subprocess.check_call(["mv", str(path) + "bis.mp3", str(path)]) + + def choose_artist(self, information): + """ + if artist exist + if cover by take following + if search + + :param information: + :return: + """ + + if "artist" in information and information["artist"] is not None: + return information["artist"] + elif self.is_title_with_artist(information["title"]): + return None + else: + return information["uploader"] + + def process_metadata(self, fullInformation): + if "_type" in fullInformation and fullInformation["_type"] == "playlist": + for entrie in fullInformation["entries"]: + artist = self.choose_artist(entrie) + if artist is not None: + self.add_metadata(config["library_path"] + "/" + str(entrie["title"]) + ".mp3", artist) + else: + artist = self.choose_artist(fullInformation) + if artist is not None: + self.add_metadata(config["library_path"] + "/" + str(fullInformation["title"]) + ".mp3", artist) + + def is_title_with_artist(self, title): + return False + + def process_url(self, url, path): + if "l.facebook.com" in url: + fb_redirection = subprocess.check_output(["curl", url]) + p = re.compile('watch\?v=(.{11})\"') + uid = p.search(fb_redirection.decode('ascii')).group(1) + else: + uid = url + ydl_opts_download['outtmpl'] = config["library_path"] + "/" + '%(title)s.%(ext)s' + fullInformation = youtube_dl.YoutubeDL(ydl_opts_title).extract_info(uid) + youtube_dl.YoutubeDL(ydl_opts_download).download([uid]) + files = glob.glob(config["library_path"] + "/*.mp3") + self.process_metadata(fullInformation) + return files diff --git a/media/mediamanager.py b/media/mediamanager.py new file mode 100644 index 0000000..d14fde7 --- /dev/null +++ b/media/mediamanager.py @@ -0,0 +1,26 @@ +import logging + +from media.downloader import Downloader +from media.uploader import Uploader +from users_push.userslibrarian import UsersLibrarian + + +class MediaManager: + downloader = None + + def __init__(self): + self.downloader = Downloader() + self.uploader = Uploader() + + def is_correct_url(self, url): + return self.downloader.is_a_correct_url(url) + + def transfer_url(self, url, user_state): + logging.info("Download of "+str(url)+"will begin") + downloads = self.downloader.process_url(url, UsersLibrarian.path_user(user_state.user_id)) + logging.info("All files ("+str(len(downloads))+") downloaded:"+str(downloads)) + + self.uploader.upload(downloads, user_state) + logging.info("All files ("+str(len(downloads))+") are uploaded:"+str(downloads)) + + diff --git a/media/uploader.py b/media/uploader.py new file mode 100644 index 0000000..faadb2c --- /dev/null +++ b/media/uploader.py @@ -0,0 +1,19 @@ +from gmusicapi import * +import logging +from users_push.userslibrarian import * + + +class Uploader: + + def upload(self, files, user_state): + cred_path = UsersLibrarian.path_user_cred(user_state.user_id) + for music in files: + mm = Musicmanager(debug_logging=False) + mm.logger.setLevel(logging.WARNING) + mm.login(oauth_credentials=cred_path, uploader_id='02:42:3D:5B:ED:7B') + code = mm.upload(music) + logging.info(str(music)+" was uploaded with return value:"+str(code)) + try: + os.remove(music) + except OSError: + pass diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_downloader.py b/tests/test_downloader.py new file mode 100644 index 0000000..34761a3 --- /dev/null +++ b/tests/test_downloader.py @@ -0,0 +1,37 @@ +from unittest import TestCase, mock + +from media.downloader import Downloader + + +class TestDownloader(TestCase): + def test_is_a_correct_url(self): + downloader = Downloader() + ret = downloader.is_a_correct_url("https://www.youtube.com/watch?v=dQw4w9WgXcQ") + self.assertTrue(ret) + + @mock.patch('subprocess.check_output') + def test_is_a_correct_url_facebook(self, subproc_mock): + downloader = Downloader() + subproc_mock.return_value = """