Files
Vocard/addons/lyrics.py
2023-09-11 20:02:08 +08:00

190 lines
8.9 KiB
Python

import aiohttp, random, bs4, re
import function as func
from abc import ABC, abstractmethod
from urllib.parse import quote
from math import floor
from importlib import import_module
userAgents = '''Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.11 Safari/535.19
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.66 Safari/535.11
Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Chrome/4.0.221.3 Safari/532.2
Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Chrome/4.0.221.0 Safari/532.2
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/532.1 (KHTML, like Gecko) Chrome/4.0.220.1 Safari/532.1
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.1 (KHTML, like Gecko) Chrome/4.0.219.6 Safari/532.1
Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/532.1 (KHTML, like Gecko) Chrome/4.0.219.5 Safari/532.1
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.1 (KHTML, like Gecko) Chrome/4.0.219.5 Safari/532.1
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.1 (KHTML, like Gecko) Chrome/4.0.219.4 Safari/532.1
Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/532.1 (KHTML, like Gecko) Chrome/4.0.219.3 Safari/532.1
Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/532.1 (KHTML, like Gecko) Chrome/4.0.219.3 Safari/532.1
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.1 (KHTML, like Gecko) Chrome/4.0.219.3 Safari/532.1
Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.197.0 Safari/532.0
Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.197.0 Safari/532.0
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/2.0.172.23 Safari/530.5
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/2.0.172.2 Safari/530.5
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/2.0.172.2 Safari/530.5
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/530.4 (KHTML, like Gecko) Chrome/2.0.172.0 Safari/530.4
Mozilla/5.0 (Windows; U; Windows NT 5.2; eu) AppleWebKit/530.4 (KHTML, like Gecko) Chrome/2.0.172.0 Safari/530.4
Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/530.4 (KHTML, like Gecko) Chrome/2.0.172.0 Safari/530.4
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/2.0.172.0 Safari/530.5
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.4 (KHTML, like Gecko) Chrome/2.0.171.0 Safari/530.4
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.1 (KHTML, like Gecko) Chrome/2.0.170.0 Safari/530.1
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.1 (KHTML, like Gecko) Chrome/2.0.169.0 Safari/530.1
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.1 (KHTML, like Gecko) Chrome/2.0.168.0 Safari/530.1
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.1 (KHTML, like Gecko) Chrome/2.0.164.0 Safari/530.1
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.0 (KHTML, like Gecko) Chrome/2.0.162.0 Safari/530.0
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/530.0 (KHTML, like Gecko) Chrome/2.0.160.0 Safari/530.0
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/528.10 (KHTML, like Gecko) Chrome/2.0.157.2 Safari/528.10
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/528.10 (KHTML, like Gecko) Chrome/2.0.157.2 Safari/528.10
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/528.11 (KHTML, like Gecko) Chrome/2.0.157.0 Safari/528.11
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/528.9 (KHTML, like Gecko) Chrome/2.0.157.0 Safari/528.9
Mozilla/5.0 (Linux; U; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13
Mozilla/5.0 (Macintosh; U; Mac OS X 10_6_1; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/ Safari/530.5
Mozilla/5.0 (Macintosh; U; Mac OS X 10_5_7; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/ Safari/530.5
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-US) AppleWebKit/530.9 (KHTML, like Gecko) Chrome/ Safari/530.9
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-US) AppleWebKit/530.6 (KHTML, like Gecko) Chrome/ Safari/530.6
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/ Safari/530.5'''
class LyricsPlatform(ABC):
@abstractmethod
async def getLyrics():
...
class A_ZLyrics(LyricsPlatform):
async def get(self, url):
try:
async with aiohttp.ClientSession() as session:
resp = await session.get(url=url, headers={'User-Agent': random.choice(userAgents)})
if resp.status != 200:
return None
return await resp.text()
except:
return ""
async def getLyrics(self, title: str):
link = await self.googleGet(title=title)
if not link:
return 0
page = await self.get(link)
metadata = [elm.text for elm in self.htmlFindAll(page)('b')]
if not metadata:
return None
try:
title = ''.join(i for i in metadata[1][1:-1] if i not in r'<>:"/\|?*')
divs = [i.text for i in self.htmlFindAll(page)('div', {'class': None})]
lyrics = max(divs, key=len).strip()
if not lyrics:
return print("Lyrics not found")
rr = re.split(r"(\[[\w\S_ ]+\:])", lyrics)
for item in rr:
if item == "":
rr.remove(item)
count = len(rr)
if count > 1:
if (count % 2) != 0:
del rr[count-1]
return {rr[i].replace("[", "").replace(":]", ""): self.clearText(rr[i + 1]) for i in range(0, len(rr), 2)}
return {"default": self.clearText(rr[0])}
except:
return None
async def googleGet(self, acc = 0.6, artist='', title=''):
data = artist + ' ' * (title != '' and artist != '') + title
encoded_data = quote(data.replace(' ', '+'))
google_page = await self.get('{}{}+site%3Aazlyrics.com'.format(
'https://duckduckgo.com/html/?q=', encoded_data))
try:
results = re.findall(r'(azlyrics\.com\/lyrics\/[a-z0-9]+\/(\w+).html)', google_page)
except:
return None
if len(results):
jaro_artist = 1.0
jaro_title = 1.0
if artist:
jaro_artist = self.jaro_distance(artist.replace(' ', ''), results[0][0])
if title:
jaro_title = self.jaro_distance(title.replace(' ', ''), results[0][1])
if jaro_artist >= acc and jaro_title >= acc:
return 'https://www.' + results[0][0]
else:
return None
return None
def jaro_distance(self, s1, s2):
if (s1 == s2):
return 1.0
len1, len2 = len(s1), len(s2)
max_dist = floor(max(len1, len2) / 2) - 1
match = 0
hash_s1, hash_s2 = [0] * len(s1), [0] * len(s2)
for i in range(len1):
for j in range(max(0, i - max_dist),
min(len2, i + max_dist + 1)):
if (s1[i] == s2[j] and hash_s2[j] == 0):
hash_s1[i], hash_s2[j] = 1, 1
match += 1
break
if (match == 0):
return 0.0
t = 0
point = 0
for i in range(len1):
if (hash_s1[i]):
while (hash_s2[point] == 0):
point += 1
if (s1[i] != s2[point]):
point += 1
t += 1
t = t//2
return (match/ len1 + match / len2 + (match - t + 1) / match)/ 3.0
def htmlFindAll(self, page):
soup = bs4.BeautifulSoup(page, "html.parser")
return soup.findAll
def clearText(self, text: str):
if text.startswith("\n\n"):
text = text.replace("\n\n", "", 1)
return text
class Genius(LyricsPlatform):
def __init__(self) -> None:
self.module = import_module("lyricsgenius")
self.genius = self.module.Genius(func.tokens.genius_token)
async def getLyrics(self, name: str):
song = self.genius.search_song(title=name)
if not song:
return None
return {"default": song.lyrics}
lyricsPlatform: dict[str, LyricsPlatform] = {
"a_zlyrics": A_ZLyrics,
"genius": Genius
}