Skip to content

Instantly share code, notes, and snippets.

@SylveonDeko
Created April 13, 2024 22:36
Show Gist options
  • Save SylveonDeko/a6b2118d4efe1a015ed7d9d01e02e22e to your computer and use it in GitHub Desktop.
Save SylveonDeko/a6b2118d4efe1a015ed7d9d01e02e22e to your computer and use it in GitHub Desktop.
/// <summary>
/// Contains logic for handling autoplay in a server. Requires either a last.fm API key.
/// </summary>
/// <returns>A bool depending on if the api key was correct.</returns>
public async Task<bool> AutoPlay()
{
var autoPlay = await GetAutoPlay();
if (autoPlay == 0)
return true;
var queue = await cache.GetMusicQueue(base.GuildId);
var lastSong = queue.MaxBy(x => x.Index);
if (lastSong is null)
return true;
LastFmResponse response;
try
{
// sorted info for attempting to fetch data from lastfm
var fullTitle = lastSong.Track.Title;
var trackTitle = fullTitle;
var artistName = lastSong.Track.Author;
var hyphenIndex = fullTitle.IndexOf(" - ");
// if the title has a hyphen, split the title and artist, used in cases where the title is formatted as "Artist - Title"
if (hyphenIndex != -1)
{
artistName = fullTitle.Substring(0, hyphenIndex).Trim();
trackTitle = fullTitle.Substring(hyphenIndex + 3).Trim();
}
// remove any extra info from the title that might be in brackets or parentheses
trackTitle = Regex.Replace(trackTitle, @"\s*\[.*?\]\s*", "", RegexOptions.Compiled);
trackTitle = Regex.Replace(trackTitle, @"\s*\([^)]*\)\s*", "", RegexOptions.Compiled);
trackTitle = trackTitle.Trim();
// Query lastfm the first time with the formatted track title that doesnt contain the artist, with artist data from the track itself
var apiResponse = await httpClient.GetStringAsync(
$"http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&artist={Uri.EscapeDataString(artistName)}&track={Uri.EscapeDataString(trackTitle)}&autocorrect=1&api_key={Uri.EscapeDataString(creds.LastFmApiKey)}&format=json");
response = JsonConvert.DeserializeObject<LastFmResponse>(apiResponse);
// If the first query returns no results, assume that the title had useful author info, use the split title and author info and try again
if (response.Similartracks.Track.Count == 0)
{
apiResponse = await httpClient.GetStringAsync(
$"http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&artist={Uri.EscapeDataString(lastSong.Track.Author)}&track={Uri.EscapeDataString(trackTitle)}&autocorrect=1&api_key={Uri.EscapeDataString(creds.LastFmApiKey)}&format=json");
response = JsonConvert.DeserializeObject<LastFmResponse>(apiResponse);
}
}
catch (Exception ex)
{
Log.Error(ex, "Invalid Last.fm credentials");
return false;
}
// If the response is empty, return true
if (response.Similartracks.Track.Count == 0)
return true;
var queuedTrackNames = new HashSet<string>(queue.Select(q => q.Track.Title));
// Filter out tracks that are already in the queue
var filteredTracks = response.Similartracks.Track
.Where(t => !queuedTrackNames.Contains($"{t.Name}"))
.ToList();
// get the amount of tracks to take, either the amount of tracks in the response or the amount of tracks to autoplay
var toTake = Math.Min(autoPlay, filteredTracks.Count);
foreach (var rec in filteredTracks.Take(toTake))
{
var trackToLoad = await audioService.Tracks.LoadTrackAsync($"{rec.Name} {rec.Artist.Name}", TrackSearchMode.YouTube);
if (trackToLoad is null)
continue;
queue.Add(new MewdekoTrack(queue.Count + 1, trackToLoad, new PartialUser()
{
AvatarUrl = client.CurrentUser.GetAvatarUrl(),
Username = "Mewdeko",
Id = client.CurrentUser.Id
}));
await cache.SetMusicQueue(base.GuildId, queue);
}
await cache.SetMusicQueue(base.GuildId, queue);
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment