Skip to content

Commit

Permalink
version 1.1
Browse files Browse the repository at this point in the history
Listen command improvement, some major message customisation
  • Loading branch information
dinoginger authored May 1, 2021
2 parents 1e81d1a + ca2f7ea commit bac40fb
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 149 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ bin/

#config file
/bot/_config.json
/bot/t_config.json

#log files
/bot/logs/

63 changes: 42 additions & 21 deletions bot/Modules/ListenCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Discord;
Expand All @@ -8,7 +10,8 @@
using SpotifyBot.Service.Spotify;
using Microsoft.Extensions.DependencyInjection;
using SpotifyBot.Other;

using SpotifyBot.Service.ForCooldown;
using Swan;


namespace SpotifyBot.Modules
Expand All @@ -17,21 +20,22 @@ public class ListenCommand : ModuleBase<SocketCommandContext>
{
private struct song_data
{
public string songname;
public int popularity;
public int s_popularity;
public int a_popularity;
public string genre_string;
}

///Default value of minutes command !listen runs, if not overloaded with minutes parameter
private const int command_cooldown = 5; //--minutes \\\\Determines cooldown for our listen command;


private const int wait_seconds = 30; //--seconds \\\\\Period of time we wait before checking song again

private SpotifyService spotify;
private ListenUsersList _listenUsersList;
private Dictionary<ulong, Tuple<TimeSpan,DateTime>> _dictionary;

public ListenCommand(IServiceProvider serviceProvider)
{
spotify = serviceProvider.GetRequiredService<SpotifyService>();
_listenUsersList = serviceProvider.GetRequiredService<ListenUsersList>();
_dictionary= _listenUsersList._UsrDict;
}

/// <summary>
Expand All @@ -42,14 +46,25 @@ public ListenCommand(IServiceProvider serviceProvider)
/// <returns></returns>

[Command("listen", RunMode = RunMode.Async)]
[MyRatelimit(1,command_cooldown,MyMeasure.Minutes, RatelimitFlags.None)]
public async Task<RuntimeResult> Listenn(float minutes,SocketUser user = null)
{
if (user == null)
{
user = Context.User;
}

DateTime utcNow = DateTime.UtcNow;
if (_dictionary.ContainsKey(user.Id))
{
return MyCommandResult.FromError($"Shhh... :eyes: 'Listen' is already running for user {user.Mention}!\nEstimated end time : `{(_dictionary[user.Id].Item1 - (utcNow - _dictionary[user.Id].Item2) ).ToString(@"hh\:mm\:ss")}`");
}
else
{
TimeSpan span = TimeSpan.FromMinutes(minutes); // converting float minutes to timespan minutes
_dictionary.Add(user.Id, new Tuple<TimeSpan, DateTime>(span, utcNow)); //filling dict
}


Random random = new Random();
Color color = new Color(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255));
try
Expand Down Expand Up @@ -81,14 +96,13 @@ public async Task<RuntimeResult> Listenn(float minutes,SocketUser user = null)
if (activity is SpotifyGame spot)
{
Spotify_exists = true;
Console.WriteLine($"{d + 1} song recieved");
//Console.WriteLine($"{d + 1} song recieved");
var tuple = spotify.Listen(spot.TrackTitle + " " + spot.Artists.First());
songData[d].popularity = tuple.Result.Item1;
songData[d].genre_string = tuple.Result.Item2;

songData[d].songname = spot.TrackTitle;
Console.WriteLine(spot.TrackTitle);
Console.WriteLine(songData[d].genre_string);
songData[d].s_popularity = tuple.Result.Item1; // <- song pop
songData[d].a_popularity = tuple.Result.Item2; // <- artist pop
songData[d].genre_string = tuple.Result.Item3;
//Console.WriteLine(spot.TrackTitle);
//Console.WriteLine(songData[d].genre_string);
d++;
}
}
Expand All @@ -108,14 +122,14 @@ public async Task<RuntimeResult> Listenn(float minutes,SocketUser user = null)
//Console.WriteLine("\n\n");

var distinct_data = songData.Distinct(); //Deletes similar elements.
int[] popularities = new int[distinct_data.Count()];
float[] popularities = new float[distinct_data.Count()];// song popularities
int dd = 0;
string distinct_genres = "";
foreach (var data in distinct_data)
{
Console.WriteLine(data.songname);
Console.WriteLine(data.genre_string);
popularities[dd] = data.popularity;
//Console.WriteLine(data.songname);
//Console.WriteLine(data.genre_string);
popularities[dd] = (data.s_popularity*0.25f + data.a_popularity*0.75f);
dd++;
distinct_genres = distinct_genres + "+" + data.genre_string;//all genres to one string, in order to pass it to GetTopGenres();
}
Expand Down Expand Up @@ -153,16 +167,23 @@ public async Task<RuntimeResult> Listenn(float minutes,SocketUser user = null)
embedBuilder.AddField(genre_field);
}

await Context.Channel.SendMessageAsync("", false, embedBuilder.Build());
RemoveUser(user,_dictionary);
await Context.Channel.SendMessageAsync(user.Mention, false, embedBuilder.Build());
return MyCommandResult.FromSuccess();
}
catch (Exception e)
{

RemoveUser(user, _dictionary);
return MyCommandResult.FromError($"Command aborted : {e.Message}");
}
}


//Removes element from dict, thats all
private void RemoveUser(SocketUser user, Dictionary<ulong, Tuple<TimeSpan,DateTime>> _dict)
{
_dict.Remove(user.Id);
}
}
}

Expand Down
8 changes: 4 additions & 4 deletions bot/Modules/SearchCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ namespace SpotifyBot.Modules
{
public class SearchCommand : ModuleBase<SocketCommandContext>
{
private SpotifyService spotify;
private SpotifyService spotifyService;
public SearchCommand(IServiceProvider serviceProvider)
{
spotify = serviceProvider.GetRequiredService<SpotifyService>();
spotifyService = serviceProvider.GetRequiredService<SpotifyService>();
}


Expand All @@ -25,15 +25,15 @@ public async Task<RuntimeResult> search([Remainder] string msg)
Console.WriteLine("we in!");
try
{
EmbedBuilder embedBuilerr = await spotify.Search(msg, Context.User);
EmbedBuilder embedBuilerr = await spotifyService.Search(msg, Context.User);
await Context.Channel.SendMessageAsync("", false, embedBuilerr.Build());
return MyCommandResult.FromSuccess();
}
catch (Exception e)
{
Console.WriteLine("we messed up");
return MyCommandResult.FromError(e.Message);
}
return MyCommandResult.FromSuccess();
}
}
}
24 changes: 2 additions & 22 deletions bot/Other/MyRateLimit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Discord.Commands;
using Microsoft.Extensions.DependencyInjection;
using SpotifyBot.Service;
using SpotifyBot.Service.ForCooldown;

namespace SpotifyBot.Other
{
Expand Down Expand Up @@ -111,22 +112,7 @@ public override Task<PreconditionResult> CheckPermissionsAsync(
CommandInfo _,
IServiceProvider __)
{
var a = __.GetService<_CooldownFixer>();

//checking if this command exists
//if not we create and setup first run as unsucessful (to skip and rely on command handler next time)
if (!(a.ifFailed.ContainsKey(context.User.Username)))
{
var user_dict = new Dictionary<string, bool>();
a.ifFailed.Add(context.User.Username,user_dict);
user_dict.Add(_.Name,true);
}

if (!(a.ifFailed[context.User.Username].ContainsKey(_.Name)))
{
a.ifFailed[context.User.Username].Add(_.Name,true);

}


if (this._noLimitInDMs && context.Channel is IPrivateChannel)
Expand All @@ -137,19 +123,13 @@ public override Task<PreconditionResult> CheckPermissionsAsync(
CommandTimeout commandTimeout1;
CommandTimeout commandTimeout2 = !this._invokeTracker.TryGetValue(key, out commandTimeout1) || !(utcNow - commandTimeout1.FirstInvoke < this._invokeLimitPeriod) ? new CommandTimeout(utcNow) : commandTimeout1;
++commandTimeout2.TimesInvoked;
if (a.ifFailed[context.User.Username][_.Name])//if null wont enter
{
commandTimeout2.TimesInvoked -= 1;
}

if (commandTimeout2.TimesInvoked >= this._invokeLimit)
if (commandTimeout2.TimesInvoked >= this._invokeLimit && (((this._invokeLimitPeriod - (utcNow - commandTimeout2.FirstInvoke) != this._invokeLimitPeriod))))
{
a.ifFailed[context.User.Username][_.Name] = false;
return Task.FromResult<PreconditionResult>(PreconditionResult.FromError(this.ErrorMessage ?? $"Sheesh.. :eyes: this command is on cooldown for `{(this._invokeLimitPeriod - (utcNow - commandTimeout2.FirstInvoke)).ToString(@"hh\:mm\:ss")}`"));
}

this._invokeTracker[key] = commandTimeout2;
a.ifFailed[context.User.Username][_.Name] = false;
return Task.FromResult<PreconditionResult>(PreconditionResult.FromSuccess());
}

Expand Down
14 changes: 10 additions & 4 deletions bot/Other/UserErrorResponses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,24 @@ namespace SpotifyBot.Other
public class UserErrorResponses
{
private const string listen_response =
"Hey, this commands input parameters are `<<listen [minutes]` or `<<listen [minutes] [@mention]`";
" :robot: Hey, this command's input parameters are `<<listen [minutes]` or `<<listen [minutes] [@mention]`\nFor full command list type `<<help`";

private const string search_response = "Hey, this commands input parameter is `<<search <search request>`";
private const string search_response = " :robot: Hey, this command's input parameter is `<<search [search request]`\nFor full command list type `<<help`";
public static async Task BadArg_Parse_Response(Optional<CommandInfo> command, ICommandContext context)
{
if (command.Value.Name == "listen")
{
await context.Channel.SendMessageAsync(listen_response);
EmbedBuilder embed = new EmbedBuilder();
embed.WithDescription(listen_response);
embed.Color = Color.Gold;
await context.Channel.SendMessageAsync("", false, embed.Build());
}
else if (command.Value.Name == "search")
{
await context.Channel.SendMessageAsync(search_response);
EmbedBuilder embed = new EmbedBuilder();
embed.WithDescription(search_response);
embed.Color = Color.Gold;
await context.Channel.SendMessageAsync("", false, embed.Build());
}
}
}
Expand Down
20 changes: 5 additions & 15 deletions bot/Service/CommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SpotifyBot.Other;
using SpotifyBot.Service.ForCooldown;


namespace SpotifyBot.Service
Expand Down Expand Up @@ -51,27 +52,16 @@ public async Task OnCommandExecutedAsync(Optional<CommandInfo> command, ICommand
{
if (result.Error != CommandError.UnknownCommand)
{
await context.Channel.SendMessageAsync(result.ErrorReason);
EmbedBuilder embed = new EmbedBuilder();
embed.WithDescription(result.ErrorReason);
embed.Color = Color.Red;
await context.Channel.SendMessageAsync("", false, embed.Build());
}

}


//This is run for cooldown issue.

var a = _services.GetService<_CooldownFixer>();



a.ifFailed[context.User.Username][command.Value.Name] = true;


if (a.ifFailed[context.User.Username].Count > 1000) //if thing is used by more than 1000 ppl
{
a.ifFailed[context.User.Username].Clear(); //clear
}


var commandName = command.IsSpecified ? command.Value.Name : "A command";
if (result.Error != CommandError.UnmetPrecondition && result.Error != CommandError.UnknownCommand) //Ignore ratelimits, they will occur a lot.
{
Expand Down
20 changes: 20 additions & 0 deletions bot/Service/ForCooldown/ListenUsersList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;

namespace SpotifyBot.Service.ForCooldown
{

/// <summary>
/// This thingy checks if command "listen" is still running for specified user.
/// this will add every user's (who has program listen running) ID to list.
/// </summary>
public class ListenUsersList
{
/// <summary>
/// First Key : user.id,
/// first tuple item : Time span listen minutes, requested by user
/// second tuple item : utcNow of command start
/// </summary>
public Dictionary<ulong, Tuple<TimeSpan,DateTime>> _UsrDict = new Dictionary<ulong,Tuple<TimeSpan,DateTime>>();
}
}
33 changes: 22 additions & 11 deletions bot/Service/LoggingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ public class LoggingService
private readonly CommandService _commands;

public LoggingService(IServiceProvider services)
{
{
// get the services we need via DI, and assign the fields declared above to them
_client = services.GetRequiredService<DiscordSocketClient>();
_client = services.GetRequiredService<DiscordSocketClient>();
_commands = services.GetRequiredService<CommandService>();
_logger = services.GetRequiredService<ILogger<LoggingService>>(); //<ILogger<LoggingService>>() injecting logger to logging service???
_logger = services
.GetRequiredService<ILogger<LoggingService>
>(); //<ILogger<LoggingService>>() injecting logger to logging service???

// hook into these events with the methods provided below
_client.Ready += OnReadyAsync;
_client.Log += OnLogAsync;
_commands.Log += OnLogAsync;

}

// this method executes on the bot being connected/ready
Expand All @@ -37,12 +39,22 @@ public Task OnReadyAsync()
_logger.LogInformation($"We are on [{_client.Guilds.Count}] servers");
return Task.CompletedTask;
}

// this method switches out the severity level from Discord.Net's API, and logs appropriately
public Task OnLogAsync(LogMessage msg)
public async Task OnLogAsync(LogMessage msg)
{
string logText = $": {msg.Exception?.ToString() ?? msg.Message}";

if (msg.Exception is CommandException cmdException)
{
// We can tell the user that something unexpected has happened
await cmdException.Context.Channel.SendMessageAsync("Something went catastrophically wrong!");

// We can also log this incident
Console.WriteLine(
$"{cmdException.Context.User} failed to execute '{cmdException.Command.Name}' in {cmdException.Context.Channel}.");
}

switch (msg.Severity.ToString())
{
case "Critical":
Expand All @@ -64,20 +76,19 @@ public Task OnLogAsync(LogMessage msg)
{
_logger.LogInformation(logText);
break;
}
}
case "Debug":
{
_logger.LogDebug(logText);
break;
}
}
case "Error":
{
_logger.LogError(logText);
break;
}
}
}

return Task.CompletedTask;
}
}
}
}
Loading

0 comments on commit bac40fb

Please sign in to comment.