misc/version bump

This commit is contained in:
codey 2025-02-05 20:23:06 -05:00
parent bc333b4258
commit ec80a33298
10 changed files with 97 additions and 117 deletions

View File

@ -16,12 +16,12 @@ logger.setLevel(logging.INFO)
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
app = FastAPI(title="codey.lol API", app = FastAPI(title="codey.lol API",
version="0.1a", version="1.0",
contact={ contact={
'name': 'codey' 'name': 'codey'
}, },
redirect_slashes=False,
loop=loop) loop=loop)
app.loop = loop
constants = importlib.import_module("constants").Constants() constants = importlib.import_module("constants").Constants()
util = importlib.import_module("util").Utilities(app, constants) util = importlib.import_module("util").Utilities(app, constants)
@ -82,6 +82,7 @@ End Blacklisted Routes
""" """
Actionable Routes Actionable Routes
""" """
randmsg_endpoint = importlib.import_module("endpoints.rand_msg").RandMsg(app, util, constants, glob_state) randmsg_endpoint = importlib.import_module("endpoints.rand_msg").RandMsg(app, util, constants, glob_state)
transcription_endpoints = importlib.import_module("endpoints.transcriptions").Transcriptions(app, util, constants, glob_state) transcription_endpoints = importlib.import_module("endpoints.transcriptions").Transcriptions(app, util, constants, glob_state)
ai_endpoints = importlib.import_module("endpoints.ai").AI(app, util, constants, glob_state) ai_endpoints = importlib.import_module("endpoints.ai").AI(app, util, constants, glob_state)

View File

@ -64,22 +64,22 @@ class LastFM(FastAPI):
self.lastfm = importlib.import_module("lastfm_wrapper").LastFM() self.lastfm = importlib.import_module("lastfm_wrapper").LastFM()
self.endpoints = { self.endpoints = {
"get_artist_by_name": self.artist_by_name_handler, "lastfm/get_artist_by_name": self.artist_by_name_handler,
"get_artist_albums": self.artist_album_handler, "lastfm/get_artist_albums": self.artist_album_handler,
"get_release": self.release_detail_handler, "lastfm/get_release": self.release_detail_handler,
"get_release_tracklist": self.release_tracklist_handler, "lastfm/get_release_tracklist": self.release_tracklist_handler,
"get_track_info": self.track_info_handler, "lastfm/get_track_info": self.track_info_handler,
#tbd #tbd
} }
for endpoint, handler in self.endpoints.items(): for endpoint, handler in self.endpoints.items():
app.add_api_route(f"/{endpoint}", handler, methods=["POST"], app.add_api_route(f"/{endpoint}", handler, methods=["POST"],
include_in_schema=False) include_in_schema=True)
async def artist_by_name_handler(self, data: ValidArtistSearchRequest): async def artist_by_name_handler(self, data: ValidArtistSearchRequest):
""" """
/get_artist_by_name/
Get artist info Get artist info
- **a**: Artist to search
""" """
artist = data.a.strip() artist = data.a.strip()
if not artist: if not artist:
@ -102,8 +102,8 @@ class LastFM(FastAPI):
async def artist_album_handler(self, data: ValidArtistSearchRequest): async def artist_album_handler(self, data: ValidArtistSearchRequest):
""" """
/get_artist_albums/
Get artist's albums/releases Get artist's albums/releases
- **a**: Artist to search
""" """
artist = data.a.strip() artist = data.a.strip()
if not artist: if not artist:
@ -130,8 +130,9 @@ class LastFM(FastAPI):
async def release_detail_handler(self, data: ValidAlbumDetailRequest): async def release_detail_handler(self, data: ValidAlbumDetailRequest):
""" """
/get_release/
Get details of a particular release by an artist Get details of a particular release by an artist
- **a**: Artist to search
- **a2**: Release title to search (subject to change)
""" """
artist = data.a.strip() artist = data.a.strip()
release = data.a2.strip() release = data.a2.strip()
@ -158,8 +159,9 @@ class LastFM(FastAPI):
async def release_tracklist_handler(self, data: ValidAlbumDetailRequest): async def release_tracklist_handler(self, data: ValidAlbumDetailRequest):
""" """
/get_release_tracklist/
Get track list for a particular release by an artist Get track list for a particular release by an artist
- **a**: Artist to search
- **a2**: Release title to search (subject to change)
""" """
artist = data.a.strip() artist = data.a.strip()
release = data.a2.strip() release = data.a2.strip()
@ -182,8 +184,9 @@ class LastFM(FastAPI):
async def track_info_handler(self, data: ValidTrackInfoRequest): async def track_info_handler(self, data: ValidTrackInfoRequest):
""" """
/get_track_info/
Get track info from Last.FM given an artist/track Get track info from Last.FM given an artist/track
- **a**: Artist to search
- **t**: Track title to search
""" """
try: try:
artist = data.a artist = data.a

View File

@ -59,15 +59,6 @@ class ValidTypeAheadRequest(BaseModel):
pre_query: str|None = None pre_query: str|None = None
query: str query: str
class ValidLyricSearchLogRequest(BaseModel):
"""
- **webradio**: whether or not to include requests generated automatically by the radio page on codey.lol, defaults to False
"""
webradio: bool = False
class CacheUtils: class CacheUtils:
"""Lyrics Cache DB Utils""" """Lyrics Cache DB Utils"""
def __init__(self): def __init__(self):
@ -103,8 +94,8 @@ class LyricSearch(FastAPI):
self.endpoints = { self.endpoints = {
"typeahead/artist": self.artist_typeahead_handler, "typeahead/artist": self.artist_typeahead_handler,
"typeahead/song": self.song_typeahead_handler, "typeahead/song": self.song_typeahead_handler,
"lyric_search": self.lyric_search_handler, "lyric_search": self.lyric_search_handler, # Preserving old endpoint path temporarily
# "lyric_cache_list": self.lyric_cache_list_handler, "lyric/search": self.lyric_search_handler,
} }
self.acceptable_request_sources = [ self.acceptable_request_sources = [
@ -122,17 +113,8 @@ class LyricSearch(FastAPI):
self.lrc_regex = regex.compile(r'\[([0-9]{2}:[0-9]{2})\.[0-9]{1,3}\](\s(.*)){0,}') self.lrc_regex = regex.compile(r'\[([0-9]{2}:[0-9]{2})\.[0-9]{1,3}\](\s(.*)){0,}')
for endpoint, handler in self.endpoints.items(): for endpoint, handler in self.endpoints.items():
_schema_include = endpoint in ["lyric_search"] _schema_include = endpoint in ["lyric/search"]
app.add_api_route(f"/{endpoint}", handler, methods=["POST"], include_in_schema=_schema_include) app.add_api_route(f"/{endpoint}", handler, methods=["POST"], include_in_schema=_schema_include)
# async def lyric_cache_list_handler(self):
# """
# Get currently cached lyrics entries
# """
# return {
# 'err': False,
# 'data': await self.lyrics_engine.listCacheEntries()
# }
async def artist_typeahead_handler(self, data: ValidTypeAheadRequest): async def artist_typeahead_handler(self, data: ValidTypeAheadRequest):
"""Artist Type Ahead Handler""" """Artist Type Ahead Handler"""
@ -160,16 +142,6 @@ class LyricSearch(FastAPI):
typeahead_list = [str(r.get('song')) for r in typeahead_result] typeahead_list = [str(r.get('song')) for r in typeahead_result]
return typeahead_list return typeahead_list
# async def lyric_search_log_handler(self, data: ValidLyricSearchLogRequest):
# """Lyric Search Log Handler"""
# include_radio = data.webradio
# await self.glob_state.increment_counter('lyrichistory_requests')
# last_10k_sings = await self.lyrics_engine.getHistory(limit=10000, webradio=include_radio)
# return {
# 'err': False,
# 'history': last_10k_sings
# }
async def lyric_search_handler(self, data: ValidLyricRequest): async def lyric_search_handler(self, data: ValidLyricRequest):
""" """
Search for lyrics Search for lyrics

View File

@ -57,7 +57,7 @@ class Misc(FastAPI):
#TODO: change URL below to dynamically populate based on listener #TODO: change URL below to dynamically populate based on listener
async with ClientSession() as session: async with ClientSession() as session:
async with await session.post("http://127.0.0.1:52111/xc/", json=json_payload, async with await session.post("http://127.0.0.1:52111/xc", json=json_payload,
headers=headers, timeout=ClientTimeout(connect=3, sock_read=2)) as request: headers=headers, timeout=ClientTimeout(connect=3, sock_read=2)) as request:
request.raise_for_status() request.raise_for_status()
request_json = await request.json() request_json = await request.json()

View File

@ -28,7 +28,6 @@ class RandMsg(FastAPI):
async def randmsg_handler(self, data: RandMsgRequest = None): async def randmsg_handler(self, data: RandMsgRequest = None):
""" """
/randmsg
Get a randomly generated message Get a randomly generated message
""" """
random.seed() random.seed()

View File

@ -54,36 +54,40 @@ class XC(FastAPI):
/xc /xc
Handle XC Commands Handle XC Commands
""" """
key = data.key
bid = data.bid
cmd = data.cmd
cmd_data = data.data
req_type = 0
if bid in [1]:
req_type = 2
if not self.util.check_key(path=request.url.path, req_type=req_type, key=key):
raise HTTPException(status_code=403, detail="Unauthorized")
BID_ADDR_MAP = { try:
0: '10.10.10.101:5991', # Thomas/Aces key = data.key
1: '10.10.10.100:5992' # MS & Waleed Combo bid = data.bid
} cmd = data.cmd
cmd_data = data.data
req_type = 0
if not bid in BID_ADDR_MAP: if bid in [1]:
return { req_type = 2
'err': True,
'errorText': 'Invalid bot id'
}
bot_api_url = f'http://{BID_ADDR_MAP[bid]}/' if not self.util.check_key(path=request.url.path, req_type=req_type, key=key):
async with ClientSession() as session: raise HTTPException(status_code=403, detail="Unauthorized")
async with await session.post(f"{bot_api_url}{cmd}", json=cmd_data, headers={
'Content-Type': 'application/json; charset=utf-8' BID_ADDR_MAP = {
}, timeout=ClientTimeout(connect=5, sock_read=5)) as request: 0: '10.10.10.101:5991', # Thomas/Aces
response = await request.json() 1: '10.10.10.100:5992' # MS & Waleed Combo
return { }
'success': True,
'response': response if not bid in BID_ADDR_MAP:
} return {
'err': True,
'errorText': 'Invalid bot id'
}
bot_api_url = f'http://{BID_ADDR_MAP[bid]}/'
async with ClientSession() as session:
async with await session.post(f"{bot_api_url}{cmd}", json=cmd_data, headers={
'Content-Type': 'application/json; charset=utf-8'
}, timeout=ClientTimeout(connect=5, sock_read=5)) as request:
response = await request.json()
return {
'success': True,
'response': response
}
except:
pass

View File

@ -22,18 +22,18 @@ class YT(FastAPI):
self.ytsearch = importlib.import_module("youtube_search_async").YoutubeSearch() self.ytsearch = importlib.import_module("youtube_search_async").YoutubeSearch()
self.endpoints = { self.endpoints = {
"yt_video_search": self.yt_video_search_handler, "yt/search": self.yt_video_search_handler,
#tbd #tbd
} }
for endpoint, handler in self.endpoints.items(): for endpoint, handler in self.endpoints.items():
app.add_api_route(f"/{endpoint}", handler, methods=["POST"], app.add_api_route(f"/{endpoint}", handler, methods=["POST"],
include_in_schema=False) include_in_schema=True)
async def yt_video_search_handler(self, data: ValidYTSearchRequest): async def yt_video_search_handler(self, data: ValidYTSearchRequest):
""" """
/yt_video_search
Search for YT Video by Title (closest match returned) Search for YT Video by Title (closest match returned)
- **t**: Title to search
""" """
title = data.t title = data.t

View File

@ -26,7 +26,7 @@ class LastFM:
} }
async with ClientSession() as session: async with ClientSession() as session:
async with session.get(f"{self.api_base_url}artist.getinfo&artist={artist}&api_key={self.creds.get('key')}&autocorrect=1&format=json", async with await session.get(f"{self.api_base_url}artist.getinfo&artist={artist}&api_key={self.creds.get('key')}&autocorrect=1&format=json",
timeout=ClientTimeout(connect=3, sock_read=8)) as request: timeout=ClientTimeout(connect=3, sock_read=8)) as request:
assert request.status in [200, 204] assert request.status in [200, 204]
data = await request.json() data = await request.json()
@ -57,7 +57,7 @@ class LastFM:
} }
async with ClientSession() as session: async with ClientSession() as session:
async with session.get(f"{self.api_base_url}track.getInfo&api_key={self.creds.get('key')}&autocorrect=1&artist={artist}&track={track}&format=json", async with await session.get(f"{self.api_base_url}track.getInfo&api_key={self.creds.get('key')}&autocorrect=1&artist={artist}&track={track}&format=json",
timeout=ClientTimeout(connect=3, sock_read=8)) as request: timeout=ClientTimeout(connect=3, sock_read=8)) as request:
assert request.status in [200, 204] assert request.status in [200, 204]
data = await request.json() data = await request.json()
@ -107,7 +107,7 @@ class LastFM:
} }
async with ClientSession() as session: async with ClientSession() as session:
async with session.get(f"{self.api_base_url}artist.gettopalbums&artist={artist}&api_key={self.creds.get('key')}&autocorrect=1&format=json", async with await session.get(f"{self.api_base_url}artist.gettopalbums&artist={artist}&api_key={self.creds.get('key')}&autocorrect=1&format=json",
timeout=ClientTimeout(connect=3, sock_read=8)) as request: timeout=ClientTimeout(connect=3, sock_read=8)) as request:
assert request.status in [200, 204] assert request.status in [200, 204]
data = await request.json() data = await request.json()
@ -154,7 +154,7 @@ class LastFM:
} }
async with ClientSession() as session: async with ClientSession() as session:
async with session.get(f"{self.api_base_url}artists/{artist_id}?key={self.creds.get('key')}&secret={self.creds.get('secret')}", async with await session.get(f"{self.api_base_url}artists/{artist_id}?key={self.creds.get('key')}&secret={self.creds.get('secret')}",
timeout=ClientTimeout(connect=3, sock_read=8)) as request: timeout=ClientTimeout(connect=3, sock_read=8)) as request:
assert request.status in [200, 204] assert request.status in [200, 204]
data = await request.json() data = await request.json()
@ -205,7 +205,7 @@ class LastFM:
} }
async with ClientSession() as session: async with ClientSession() as session:
async with session.get(f"{self.api_base_url}album.getinfo&artist={artist}&album={album}&api_key={self.creds.get('key')}&autocorrect=1&format=json", async with await session.get(f"{self.api_base_url}album.getinfo&artist={artist}&album={album}&api_key={self.creds.get('key')}&autocorrect=1&format=json",
timeout=ClientTimeout(connect=3, sock_read=8)) as request: timeout=ClientTimeout(connect=3, sock_read=8)) as request:
assert request.status in [200, 204] assert request.status in [200, 204]
data = await request.json() data = await request.json()

View File

@ -242,37 +242,40 @@ class Cache:
logging.debug("Checking redis cache for %s...", logging.debug("Checking redis cache for %s...",
f"{artist} - {song}") f"{artist} - {song}")
redis_result = await self.redis_cache.search(artist=artist, try:
redis_result = await self.redis_cache.search(artist=artist,
song=song) song=song)
if redis_result: if redis_result:
result_tracks: list = [] result_tracks: list = []
for returned in redis_result: for returned in redis_result:
(key, track) = returned (key, track) = returned
result_tracks.append((key, f"{track['artist']} - {track['song']}")) result_tracks.append((key, f"{track['artist']} - {track['song']}"))
if not random_search: if not random_search:
best_match: tuple|None = matcher.find_best_match(input_track=input_track, best_match: tuple|None = matcher.find_best_match(input_track=input_track,
candidate_tracks=result_tracks) candidate_tracks=result_tracks)
else: else:
best_match = (result_tracks[0], 100) best_match = (result_tracks[0], 100)
if best_match: if best_match:
(candidate, confidence) = best_match (candidate, confidence) = best_match
matched = self.get_matched(redis_results=redis_result, matched_candidate=candidate, matched = self.get_matched(redis_results=redis_result, matched_candidate=candidate,
confidence=confidence) confidence=confidence)
if matched: if matched:
time_end: float = time.time() time_end: float = time.time()
time_diff: float = time_end - time_start time_diff: float = time_end - time_start
matched.confidence = confidence matched.confidence = confidence
matched.time = time_diff matched.time = time_diff
logging.info("Found %s on redis cache, skipping SQLite...", logging.info("Found %s on redis cache, skipping SQLite...",
f"{artist} - {song}") f"{artist} - {song}")
await self.redis_cache.increment_found_count(self.label) await self.redis_cache.increment_found_count(self.label)
return matched return matched
except:
pass
"""SQLite: Fallback""" """SQLite: Fallback"""

View File

@ -136,6 +136,8 @@ class RedisCache:
artist = kwargs.get('artist', '') artist = kwargs.get('artist', '')
song = kwargs.get('song', '') song = kwargs.get('song', '')
lyrics = kwargs.get('lyrics') lyrics = kwargs.get('lyrics')
fuzzy_artist = None
fuzzy_song = None
is_random_search = artist == "!" and song == "!" is_random_search = artist == "!" and song == "!"
if lyrics: if lyrics:
@ -176,11 +178,7 @@ class RedisCache:
return search_res_out return search_res_out
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
if fuzzy_artist and fuzzy_song: # await self.notifier.send(f"ERROR @ {__file__.rsplit("/", maxsplit=1)[-1]}", f"{str(e)}\nSearch was: {artist} - {song}; fuzzy: {fuzzy_artist} - {fuzzy_song}")
await self.notifier.send(f"ERROR @ {__file__.rsplit("/", maxsplit=1)[-1]}", f"{str(e)}\nSearch was: {artist} - {song}; fuzzy: {fuzzy_artist} - {fuzzy_song}")
else:
await self.notifier.send(f"ERROR @ {__file__.rsplit("/", maxsplit=1)[-1]}", f"{str(e)}\nSearch was: {artist} - {song}; fuzzy: {fuzzy_artist} - {fuzzy_song}")
async def redis_store(self, sqlite_id: int, lyr_result: LyricsResult) -> None: async def redis_store(self, sqlite_id: int, lyr_result: LyricsResult) -> None:
""" """
Store lyrics to redis cache Store lyrics to redis cache