def get_link(): """ Uses youtube-dl to fetch the direct link """ try: url = request.args.get('url') data = decode_data(get_key(), url) vid_id = data['id'] title = data['title'] format = 'm4a/bestaudio' retval = get_or_create_video_download_link(vid_id, format, get_download_link_youtube) if not LOCAL: retval = encode_data(get_key(), id=vid_id, title=title, url=retval, length=data['length']) retval = url_for('download_file', url=retval) ret_dict = { 'status': 200, 'requestLocation': '/api/v1/g', 'url': retval } return jsonify(ret_dict) except Exception as e: logger.info(traceback.format_exc()) return make_error_response(msg=str(e), endpoint='/api/v1/g')
def stream_handler(): url = request.args.get('url') try: url = decode_data(get_key(), url)['url'] except Exception: return 'Bad URL', 400 mime = 'audio/mp4' if url.find('mime=audio%2Fwebm') > -1: mime = 'audio/webm' range_header = request.headers.get('Range', None) if range_header: from_bytes, until_bytes = range_header.replace('bytes=', '').split('-') if not until_bytes: until_bytes = int(from_bytes) + int( 1024 * 1024 * 1) # 1MB * 1 = 1MB headers = {'Range': 'bytes=%s-%s' % (from_bytes, until_bytes)} r = requests.get(url, headers=headers) data = r.content rv = Response(data, 206, mimetype=mime, direct_passthrough=True) rv.headers.add('Content-Range', r.headers.get('Content-Range')) return rv r = requests.get(url, stream=True) return Response(generate_data(r), mimetype=mime)
def resolve_lyrics(self, info, track): data = decode_data(get_key(), track) title = data['title'] lyrics = Lyrics.get_lyrics(title) return Lyric(lyrics=lyrics)
def resolve_search(self, info, q): raw_html = get_search_results_html(q) videos = get_videos(raw_html) return_videos = [] for _ in videos: temp = get_video_attrs(_) if temp: track = Track(id=temp['id'], track_id=encode_data( get_key(), id=temp['id'], title=temp['title'], length=temp['length']).decode("utf-8"), description=temp['description'], length=temp['length'], time=temp['time'], thumb=temp['thumb'], uploader=temp['uploader'], views=temp['views'], title=temp['title'], get_url='/api/v1' + temp['get_url'], stream_url='/api/v1' + temp['stream_url']) return_videos.append(track) return return_videos
def stream_v2(): url = request.args.get('url') try: vid_id = decode_data(get_key(), url)['id'] url = get_stream(vid_id) return jsonify(status=200, url=url) except Exception as e: return make_error_response(msg=str(e), endpoint='api/v2/stream')
def get_link_v2(): url = request.args.get('url') try: data = decode_data(get_key(), url) vid_id = data['id'] retval = get_download(vid_id) return jsonify(status=200, url=retval) except Exception as e: return make_error_response(msg=str(e), endpoint='/api/v2/g')
def stream(): url = request.args.get('url') stream_settings = { 'lo': 'webm[abr<=64]/webm[abr<=80]/m4a[abr<=64]/[abr<=96]/m4a', 'md': 'webm[abr>=64][abr<=96]/[abr>=64][abr<=96]/webm[abr>=96][abr<=128]/webm/m4a', 'hi': 'webm/m4a' } try: req = decode_data(get_key(), url) vid_id = req['id'] quality = req.get('quality', 'md') url = get_or_create_video_download_link(vid_id, stream_settings[quality], get_download_link_youtube) except Exception as e: logger.info(traceback.format_exc()) return make_error_response(msg=str(e), endpoint='api/v1/stream') return jsonify(status=200, url=url_for('stream_handler', url=encode_data(get_key(), url=url)))
def get_video_attrs(html): """ get video attributes from html """ result = {} # get video id and description regex = 'yt\-lockup\-title.*?href.*?watch\?v\=(.*?[^\"]+)' regex += '.*? title\=\"(.*?[^\"]+)' temp = re.findall(regex, html) if len(temp) and len(temp[0]) == 2: result['id'] = temp[0][0] result['title'] = html_unescape(temp[0][1]) # length length_regex = 'video\-time.*?\>([^\<]+)' temp = re.findall(length_regex, html) if len(temp) > 0: result['length'] = temp[0].strip() # uploader upl_regex = 'yt\-lockup\-byline.*?\>.*?\>([^\<]+)' temp = re.findall(upl_regex, html) if len(temp) > 0: result['uploader'] = temp[0].strip() # time ago time_regex = 'yt\-lockup\-meta\-info.*?\>.*?\>([^\<]+).*?([0-9\,]+)' temp = re.findall(time_regex, html) if len(temp) and len(temp[0]) == 2: result['time'] = temp[0][0] result['views'] = temp[0][1] # thumbnail if 'id' in result: thumb = 'https://img.youtube.com/vi/%s/0.jpg' % result['id'] result['thumb'] = thumb else: return None # Description desc_regex = 'yt-lockup-description.*?>(.*?)<' temp = re.findall(desc_regex, html) if len(temp) > 0: result['description'] = temp[0] else: result['description'] = '' # check if all items present. If not present, usually some problem in parsing if len(result) != 8: return None # return result['get_url'] = '/g?url=' + encode_data( get_key(), id=result['id'], title=result['title'], length=result['length']).decode('utf-8') result['stream_url'] = result['get_url'].replace('/g?', '/stream?', 1) return result
def download_file(): """ Download the file from the server. First downloads the file on the server using wget and then converts it using ffmpeg """ try: url = request.args.get('url') # decode info from url data = decode_data(get_key(), url) vid_id = data['id'] url = data['url'] filename = get_filename_from_title(data['title'], ext='') m4a_path = 'static/%s.m4a' % vid_id # ^^ vid_id regex is filename friendly [a-zA-Z0-9_-]{11} # Handle partial request range_header = request.headers.get('Range', None) if range_header: from_bytes, until_bytes = range_header.replace('bytes=', '').split('-') if not until_bytes: until_bytes = int(from_bytes) + int( 1024 * 1024 * 1) # 1MB * 1 = 1MB headers = {'Range': 'bytes=%s-%s' % (from_bytes, until_bytes)} resp = requests.get(url, headers=headers, stream=True) rv = Response(generate_data(resp), 206, mimetype='audio/mp4', direct_passthrough=True) rv.headers.add('Content-Range', resp.headers.get('Content-Range')) rv.headers.add('Content-Disposition', 'attachment; filename="%s"' % filename) rv.headers.add('Content-Length', resp.headers['Content-Length']) return rv resp = requests.get(url, stream=True) filename += '.m4a' response = Response(generate_data(resp), mimetype='audio/mp4') # set headers # http://stackoverflow.com/questions/93551/how-to-encode-the-filename- response.headers.add('Content-Disposition', 'attachment; filename="%s"' % filename) response.headers.add('Content-Length', resp.headers['Content-Length']) return response except Exception as e: logger.info(traceback.format_exc()) return 'Bad things have happened', 500
def get_suggestions(vid_id, get_url_prefix='/api/v1'): url = "https://www.youtube.com/watch?v=" + vid_id raw_html = open_page(url) area_of_concern = ' '.join( area_of_concern_regex.findall(raw_html, re.DOTALL)) videos_html = videos_html_regex.findall(area_of_concern, re.DOTALL) ret_list = [] for video in videos_html: try: _id = single_video_regex['id'].findall(video)[0] if '&list=' in _id: continue title = single_video_regex['title'].findall(video)[0] duration = single_video_regex['duration'].findall(video)[0] uploader = single_video_regex['uploader'].findall(video)[0] views = single_video_regex['views'].findall(video)[0] encoded_data = encode_data(get_key(), id=_id, title=title, length=duration).decode('utf-8') get_url = get_url_prefix + '/g?url=' + encoded_data stream_url = get_url.replace('/g?', '/stream?', 1) suggest_url = get_url.replace('/g?', '/suggest?', 1) ret_list.append({ "id": _id, "title": html_unescape(title), "length": duration, "uploader": uploader, "thumb": 'https://img.youtube.com/vi/%s/0.jpg' % _id, "get_url": get_url, "stream_url": stream_url, "views": views, "suggest_url": suggest_url }) except Exception: print('Error while getting suggestion at video \n' + video) traceback.print_exc() return ret_list
def get_trending_videos(html): """ Get trending youtube videos from html """ regex = '<tr.*?data-video-id="(.*?)".*?src="(.*?)".*?<a cl.*?>(.*?)</a>.*?by.*?>(.*?)</a>.*?<span .*?>(.*?)</' raw_results = re.findall( regex, html, re.DOTALL )[:int(environ.get('PLAYLIST_VIDEOS_LIMIT', 100))] vids = [] for raw_result in raw_results: try: url = 'https://www.youtube.com/watch?v=' + raw_result[0] html = open_page(url) vids.append( { 'id': raw_result[0], 'thumb': 'https://img.youtube.com/vi/{0}/0.jpg'.format(raw_result[0]), 'title': html_unescape(raw_result[2].strip()), 'uploader': raw_result[3], 'length': raw_result[4], 'views': get_views(html), 'get_url': encode_data( get_key(), id=raw_result[0], title=raw_result[2].strip(), length=raw_result[4] ), 'description': html_unescape(get_description(html)) } ) except Exception as e: logger.info( 'Getting trending video failed. Message: %s, Video: %s' % ( str(e), raw_result[0] ) ) return vids
def resolve_tracks(self, info, filter, limit): res = requests.get( f"http://localhost:5000/api/v1/trending?type={filter}&number={limit}" ) data = res.json() l = [] for d in data['results'][str(filter)]: t = Track( id=d['id'], length=d['length'], title=d['title'], get_url=d['get_url'], suggest_url=d['suggest_url'], stream_url=d['stream_url'], thumb=d['thumb'], track_id=encode_data(get_key(), id=d['id'], title=d['title'], length=d['length']).decode("utf-8"), ) l.append(t) return l
def suggest_songs(): try: url = request.args.get('url') decoded_data = decode_data(get_key(), url) vid_id = decoded_data["id"] vids = get_suggestions(vid_id) count = len(vids) return jsonify({ "status": 200, "request_location": "/api/v1/suggest", "metadate": { "count": count }, "results": vids }) except Exception as e: logger.info(traceback.format_exc()) return make_error_response(msg=str(e), endpoint='/api/v1/suggest')