private string FormatLink(string text, Dictionary <string, string> externUrls, bool trim = true) { text = text.Truncate(trim ? 22 : int.MaxValue); if (externUrls.ContainsKey("spotify")) { return(DiscordHelpers.BuildMarkdownUri(text, externUrls["spotify"])); } else { return(text); } }
private void OnNotify(object state) { TaskHelper.FireForget(async() => { try { var(serverId, _) = ((ulong, int))state; if (!_notifications.TryGetValue(serverId, out var context)) { return; } using (await context.Lock.ClaimAsync()) { if (!context.ValidateCallback(state)) { return; // Old timer (can happen due to timer race conditions) } var guild = _client.GetGuild(serverId) as IGuild; if (guild == null) { _logger.LogInformation("Server {" + LogFields.GuildId + "} not found", serverId); return; } var logger = _logger.WithScope(guild); var settings = await _settings.Read <ScheduleSettings>(serverId, false); if (settings == null) { logger.LogWarning("Settings for server not found"); return; } var dueTime = context.UtcDueTime.Value.Add(settings.TimezoneOffset); var events = settings.Events.Where(x => x.Date == dueTime && x.HasTime && x.Notify); foreach (var e in events) { foreach (var s in settings.Notifications.Where(x => e.FitsTag(x.Tag))) { try { var channel = await guild.GetTextChannelAsync(s.Channel); if (channel == null) { continue; } var role = s.Role != default ? guild.GetRole(s.Role) : null; var embed = new EmbedBuilder() .WithTitle("🔔 Schedule") .WithDescription($"{(e.HasLink ? DiscordHelpers.BuildMarkdownUri(e.Description, e.Link) : e.Description)} is now on!"); await channel.SendMessageAsync(role != null ? $"{role.Mention} " : "", embed: embed.Build()); logger.LogInformation("Notified event {ScheduleEventDescription} ({ScheduleEventDate}, TZ: {ScheduleTimezone}, ID: {ScheduleEventId})", e.Description, e.Date, settings.TimezoneOffset, e.Id); } catch (Exception ex) { logger.LogError(ex, "Failed to notify event {ScheduleEventDescription} ({ScheduleEventId})", e.Description, e.Id); } } } var now = DateTime.UtcNow.Add(settings.TimezoneOffset); var next = settings.Events.SkipWhile(x => x.Date <= dueTime).FirstOrDefault(x => x.Notify && x.HasTime); if (next == default) { context.Disable(); return; } context.Replan(next.Date - now, next.Date.Subtract(settings.TimezoneOffset)); } } catch (Exception ex) { _logger.LogError(ex, "Failed to process event notifications"); } }); }
private string FormatLink(string text, string url, bool trim = false) => DiscordHelpers.BuildMarkdownUri(text.Truncate(trim ? 22 : int.MaxValue), url);
public async Task NowPlaying(ICommand command) { try { var(settings, user) = await GetLastFmSettings(command["User"], (IGuildUser)command.Author); var client = new LastFmClient(settings.LastFmUsername, _integrationOptions.Value.LastFmKey); var topTracksTask = client.GetTopTracks(LastFmDataPeriod.Month, 100); var tracks = (await client.GetRecentTracks(count: 1)).ToList(); if (!tracks.Any()) { await command.Reply(GetNoScrobblesMessage((await command["User"].AsGuildUserOrName)?.Item2)); return; } var nowPlaying = tracks[0].NowPlaying; var current = await client.GetTrackInfo(tracks[0].Artist.Name, tracks[0].Name); // Description var description = new StringBuilder(); description.AppendLine($"**{FormatTrackLink(current ?? tracks[0].ToTrack())}** by **{FormatArtistLink(current?.Artist ?? tracks[0].Artist)}**"); if (!string.IsNullOrEmpty(current?.Album?.Name)) { description.AppendLine($"On {DiscordHelpers.BuildMarkdownUri(current.Album.Name, current.Album.Url)}"); } else if (!string.IsNullOrEmpty(tracks[0].Album?.Name)) { description.AppendLine($"On {tracks[0].Album.Name}"); } var embed = new EmbedBuilder() .WithDescription(description.ToString()) .WithColor(0xd9, 0x23, 0x23); // Image var imageUri = current?.Album?.ImageUri ?? tracks[0]?.Album?.ImageUri; if (imageUri != null) { embed.WithThumbnailUrl(imageUri.AbsoluteUri); } // Title var author = new EmbedAuthorBuilder().WithIconUrl(_websiteWalker.LfIconUrl); if (!settings.Anonymous) { author.WithUrl($"https://www.last.fm/user/{settings.LastFmUsername}"); } if (nowPlaying) { author.WithName($"{user} is now listening to..."); } else { author.WithName($"{user} last listened to..."); } embed.WithAuthor(author); // Playcount var playCount = (current?.Playcount ?? 0) + (nowPlaying ? 1 : 0); if (playCount == 1 && current?.Playcount != null) { embed.WithFooter($"First listen"); } else if (playCount > 1) { embed.WithFooter($"{playCount.ToEnglishOrdinal()} listen"); } // Month placement { var topTracks = await topTracksTask; int counter = 0, placement = 0, placementPlaycount = int.MaxValue; foreach (var track in topTracks) { counter++; if (placementPlaycount > track.Playcount) { placementPlaycount = track.Playcount.Value; placement = counter; } if (string.Compare(track.Url, (string)(current?.Url ?? tracks[0].Url), true) == 0) { var footer = placement == 1 ? "Most played track this month" : $"{placement.ToEnglishOrdinal()} most played this month"; if (embed.Footer != null) { embed.Footer.Text += " • " + footer; } else { embed.WithFooter(footer); } break; } } } // Previous if (nowPlaying && tracks.Count > 1) { var previous = tracks[1]; embed.AddField(x => x.WithName("Previous").WithValue($"{FormatTrackLink(previous?.ToTrack())} by {FormatArtistLink(previous?.Artist)}")); } await command.Reply(embed.Build()); } catch (WebException e) when((e.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.NotFound) { ThrowUserNotFound((await command["User"].AsGuildUserOrName)?.Item2); } catch (WebException e) when((e.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.Forbidden) { throw new CommandException("The bot can't access your recently listened tracks. \n\nPlease make sure you don't have `Hide recent listening information` checked in your Last.fm settings (Settings -> Privacy -> Recent listening)."); } catch (WebException e) { await command.Reply($"Last.fm is down (error {(e.Response as HttpWebResponse)?.StatusCode.ToString() ?? e.Status.ToString()}). Please try again in a few seconds."); } }