Split Geekbot.net into src/Bot, src/Core, and src/Web
This commit is contained in:
parent
7b6dd2d2f9
commit
fc0af492ad
197 changed files with 542 additions and 498 deletions
61
src/Bot/Commands/Integrations/LolMmr/LolMmr.cs
Normal file
61
src/Bot/Commands/Integrations/LolMmr/LolMmr.cs
Normal file
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Discord.Commands;
|
||||
using Geekbot.Core;
|
||||
using Geekbot.Core.ErrorHandling;
|
||||
|
||||
namespace Geekbot.Bot.Commands.Integrations.LolMmr
|
||||
{
|
||||
public class LolMmr : ModuleBase
|
||||
{
|
||||
private readonly IErrorHandler _errorHandler;
|
||||
|
||||
public LolMmr(IErrorHandler errorHandler)
|
||||
{
|
||||
_errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
[Command("mmr", RunMode = RunMode.Async)]
|
||||
[Summary("Get the League of Legends MMR for a specified summoner")]
|
||||
public async Task GetMmr([Remainder] [Summary("summoner")] string summonerName)
|
||||
{
|
||||
try
|
||||
{
|
||||
LolMmrDto data;
|
||||
try
|
||||
{
|
||||
var name = HttpUtility.UrlEncode(summonerName.ToLower());
|
||||
var httpClient = HttpAbstractions.CreateDefaultClient();
|
||||
// setting the user agent in accordance with the whatismymmr.com api rules
|
||||
httpClient.DefaultRequestHeaders.Remove("User-Agent");
|
||||
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Linux:rocks.pizzaandcoffee.geekbot:v0.0.0");
|
||||
data = await HttpAbstractions.Get<LolMmrDto>(new Uri($"https://euw.whatismymmr.com/api/v1/summoner?name={name}"), httpClient);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
if (e.StatusCode != HttpStatusCode.NotFound) throw e;
|
||||
|
||||
await Context.Channel.SendMessageAsync("Player not found");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"**MMR for {summonerName}**");
|
||||
sb.AppendLine($"Normal: {data.Normal.Avg}");
|
||||
sb.AppendLine($"Ranked: {data.Ranked.Avg}");
|
||||
sb.AppendLine($"ARAM: {data.ARAM.Avg}");
|
||||
|
||||
await Context.Channel.SendMessageAsync(sb.ToString());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await _errorHandler.HandleCommandException(e, Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
src/Bot/Commands/Integrations/LolMmr/LolMmrDto.cs
Normal file
9
src/Bot/Commands/Integrations/LolMmr/LolMmrDto.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Geekbot.Bot.Commands.Integrations.LolMmr
|
||||
{
|
||||
public class LolMmrDto
|
||||
{
|
||||
public LolMrrInfoDto Ranked { get; set; }
|
||||
public LolMrrInfoDto Normal { get; set; }
|
||||
public LolMrrInfoDto ARAM { get; set; }
|
||||
}
|
||||
}
|
10
src/Bot/Commands/Integrations/LolMmr/LolMrrInfoDto.cs
Normal file
10
src/Bot/Commands/Integrations/LolMmr/LolMrrInfoDto.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace Geekbot.Bot.Commands.Integrations.LolMmr
|
||||
{
|
||||
public class LolMrrInfoDto
|
||||
{
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public decimal Avg { get; set; } = 0;
|
||||
}
|
||||
}
|
96
src/Bot/Commands/Integrations/MagicTheGathering.cs
Normal file
96
src/Bot/Commands/Integrations/MagicTheGathering.cs
Normal file
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Geekbot.Core.Converters;
|
||||
using Geekbot.Core.ErrorHandling;
|
||||
using Geekbot.Core.Extensions;
|
||||
using MtgApiManager.Lib.Service;
|
||||
|
||||
namespace Geekbot.Bot.Commands.Integrations
|
||||
{
|
||||
public class MagicTheGathering : ModuleBase
|
||||
{
|
||||
private readonly IErrorHandler _errorHandler;
|
||||
private readonly IMtgManaConverter _manaConverter;
|
||||
|
||||
public MagicTheGathering(IErrorHandler errorHandler, IMtgManaConverter manaConverter)
|
||||
{
|
||||
_errorHandler = errorHandler;
|
||||
_manaConverter = manaConverter;
|
||||
}
|
||||
|
||||
[Command("mtg", RunMode = RunMode.Async)]
|
||||
[Summary("Find a Magic The Gathering Card.")]
|
||||
public async Task GetCard([Remainder] [Summary("card-name")] string cardName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = await Context.Channel.SendMessageAsync($":mag: Looking up\"{cardName}\", please wait...");
|
||||
|
||||
var service = new CardService();
|
||||
var result = service
|
||||
.Where(x => x.Name, cardName)
|
||||
// fewer cards less risk of deserialization problems, don't need more than one anyways...
|
||||
.Where(x => x.PageSize, 1);
|
||||
|
||||
var card = result.All().Value.FirstOrDefault();
|
||||
if (card == null)
|
||||
{
|
||||
await message.ModifyAsync(properties => properties.Content = ":red_circle: I couldn't find a card with that name...");
|
||||
return;
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder
|
||||
{
|
||||
Title = card.Name,
|
||||
Description = card.Type
|
||||
};
|
||||
|
||||
if (card.Colors != null) eb.WithColor(GetColor(card.Colors));
|
||||
|
||||
if (card.ImageUrl != null) eb.ImageUrl = card.ImageUrl.ToString();
|
||||
|
||||
if (!string.IsNullOrEmpty(card.Text)) eb.AddField("Text", _manaConverter.ConvertMana(card.Text));
|
||||
|
||||
if (!string.IsNullOrEmpty(card.Flavor)) eb.AddField("Flavor", card.Flavor);
|
||||
if (!string.IsNullOrEmpty(card.SetName)) eb.AddInlineField("Set", card.SetName);
|
||||
if (!string.IsNullOrEmpty(card.Power)) eb.AddInlineField("Power", card.Power);
|
||||
if (!string.IsNullOrEmpty(card.Loyalty)) eb.AddInlineField("Loyality", card.Loyalty);
|
||||
if (!string.IsNullOrEmpty(card.Toughness)) eb.AddInlineField("Thoughness", card.Toughness);
|
||||
|
||||
if (!string.IsNullOrEmpty(card.ManaCost)) eb.AddInlineField("Cost", _manaConverter.ConvertMana(card.ManaCost));
|
||||
if (!string.IsNullOrEmpty(card.Rarity)) eb.AddInlineField("Rarity", card.Rarity);
|
||||
|
||||
if (card.Legalities != null && card.Legalities.Count > 0)
|
||||
eb.AddField("Legality", string.Join(", ", card.Legalities.Select(e => e.Format)));
|
||||
|
||||
await message.ModifyAsync(properties =>
|
||||
{
|
||||
properties.Content = string.Empty;
|
||||
properties.Embed = eb.Build();
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await _errorHandler.HandleCommandException(e, Context);
|
||||
}
|
||||
}
|
||||
|
||||
private Color GetColor(IEnumerable<string> colors)
|
||||
{
|
||||
var color = colors.FirstOrDefault();
|
||||
return color switch
|
||||
{
|
||||
"Black" => new Color(203, 194, 191),
|
||||
"White" => new Color(255, 251, 213),
|
||||
"Blue" => new Color(170, 224, 250),
|
||||
"Red" => new Color(250, 170, 143),
|
||||
"Green" => new Color(155, 211, 174),
|
||||
_ => new Color(204, 194, 212)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
128
src/Bot/Commands/Integrations/Mal.cs
Normal file
128
src/Bot/Commands/Integrations/Mal.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Geekbot.Core.ErrorHandling;
|
||||
using Geekbot.Core.Extensions;
|
||||
using Geekbot.Core.MalClient;
|
||||
|
||||
namespace Geekbot.Bot.Commands.Integrations
|
||||
{
|
||||
public class Mal : ModuleBase
|
||||
{
|
||||
private readonly IErrorHandler _errorHandler;
|
||||
private readonly IMalClient _malClient;
|
||||
|
||||
public Mal(IMalClient malClient, IErrorHandler errorHandler)
|
||||
{
|
||||
_malClient = malClient;
|
||||
_errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
[Command("anime", RunMode = RunMode.Async)]
|
||||
[Summary("Show Info about an Anime.")]
|
||||
public async Task SearchAnime([Remainder] [Summary("anime-name")] string animeName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_malClient.IsLoggedIn())
|
||||
{
|
||||
var anime = await _malClient.GetAnime(animeName);
|
||||
if (anime != null)
|
||||
{
|
||||
var eb = new EmbedBuilder();
|
||||
|
||||
var description = HttpUtility.HtmlDecode(anime.Synopsis)
|
||||
.Replace("<br />", "")
|
||||
.Replace("[i]", "*")
|
||||
.Replace("[/i]", "*");
|
||||
|
||||
eb.Title = anime.Title;
|
||||
eb.Description = description;
|
||||
eb.ImageUrl = anime.Image;
|
||||
eb.AddInlineField("Premiered", $"{anime.StartDate}");
|
||||
eb.AddInlineField("Ended", anime.EndDate == "0000-00-00" ? "???" : anime.EndDate);
|
||||
eb.AddInlineField("Status", anime.Status);
|
||||
eb.AddInlineField("Episodes", anime.Episodes);
|
||||
eb.AddInlineField("MAL Score", anime.Score);
|
||||
eb.AddInlineField("Type", anime.Type);
|
||||
eb.AddField("MAL Link", $"https://myanimelist.net/anime/{anime.Id}");
|
||||
|
||||
await ReplyAsync("", false, eb.Build());
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyAsync("No anime found with that name...");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyAsync(
|
||||
"Unfortunally i'm not connected to MyAnimeList.net, please tell my senpai to connect me");
|
||||
}
|
||||
}
|
||||
catch (XmlException e)
|
||||
{
|
||||
await _errorHandler.HandleCommandException(e, Context, "The MyAnimeList.net API refused to answer");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await _errorHandler.HandleCommandException(e, Context);
|
||||
}
|
||||
}
|
||||
|
||||
[Command("manga", RunMode = RunMode.Async)]
|
||||
[Summary("Show Info about a Manga.")]
|
||||
public async Task SearchManga([Remainder] [Summary("manga-name")] string mangaName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_malClient.IsLoggedIn())
|
||||
{
|
||||
var manga = await _malClient.GetManga(mangaName);
|
||||
if (manga != null)
|
||||
{
|
||||
var eb = new EmbedBuilder();
|
||||
|
||||
var description = HttpUtility.HtmlDecode(manga.Synopsis)
|
||||
.Replace("<br />", "")
|
||||
.Replace("[i]", "*")
|
||||
.Replace("[/i]", "*");
|
||||
|
||||
eb.Title = manga.Title;
|
||||
eb.Description = description;
|
||||
eb.ImageUrl = manga.Image;
|
||||
eb.AddInlineField("Premiered", $"{manga.StartDate}");
|
||||
eb.AddInlineField("Ended", manga.EndDate == "0000-00-00" ? "???" : manga.EndDate);
|
||||
eb.AddInlineField("Status", manga.Status);
|
||||
eb.AddInlineField("Volumes", manga.Volumes);
|
||||
eb.AddInlineField("Chapters", manga.Chapters);
|
||||
eb.AddInlineField("MAL Score", manga.Score);
|
||||
eb.AddField("MAL Link", $"https://myanimelist.net/manga/{manga.Id}");
|
||||
|
||||
await ReplyAsync("", false, eb.Build());
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyAsync("No manga found with that name...");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyAsync(
|
||||
"Unfortunally i'm not connected to MyAnimeList.net, please tell my senpai to connect me");
|
||||
}
|
||||
}
|
||||
catch (XmlException e)
|
||||
{
|
||||
await _errorHandler.HandleCommandException(e, Context, "The MyAnimeList.net API refused to answer");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await _errorHandler.HandleCommandException(e, Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
namespace Geekbot.Bot.Commands.Integrations.UbranDictionary
|
||||
{
|
||||
internal class UrbanListItemDto
|
||||
{
|
||||
public string Definition { get; set; }
|
||||
public string Permalink { get; set; }
|
||||
public string ThumbsUp { get; set; }
|
||||
public string Word { get; set; }
|
||||
public string Example { get; set; }
|
||||
public string ThumbsDown { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Geekbot.Bot.Commands.Integrations.UbranDictionary
|
||||
{
|
||||
internal class UrbanResponseDto
|
||||
{
|
||||
public string[] Tags { get; set; }
|
||||
public List<UrbanListItemDto> List { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Geekbot.Core;
|
||||
using Geekbot.Core.ErrorHandling;
|
||||
using Geekbot.Core.Extensions;
|
||||
|
||||
namespace Geekbot.Bot.Commands.Integrations.UbranDictionary
|
||||
{
|
||||
public class UrbanDictionary : ModuleBase
|
||||
{
|
||||
private readonly IErrorHandler _errorHandler;
|
||||
|
||||
public UrbanDictionary(IErrorHandler errorHandler)
|
||||
{
|
||||
_errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
[Command("urban", RunMode = RunMode.Async)]
|
||||
[Summary("Lookup something on urban dictionary")]
|
||||
public async Task UrbanDefine([Remainder] [Summary("word")] string word)
|
||||
{
|
||||
try
|
||||
{
|
||||
var definitions = await HttpAbstractions.Get<UrbanResponseDto>(new Uri($"https://api.urbandictionary.com/v0/define?term={word}"));
|
||||
if (definitions.List.Count == 0)
|
||||
{
|
||||
await ReplyAsync("That word hasn't been defined...");
|
||||
return;
|
||||
}
|
||||
|
||||
var definition = definitions.List.First(e => !string.IsNullOrWhiteSpace(e.Example));
|
||||
|
||||
var description = definition.Definition;
|
||||
if (description.Length > 1801)
|
||||
{
|
||||
description = description.Substring(0, 1800) + " [...]";
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder();
|
||||
eb.WithAuthor(new EmbedAuthorBuilder
|
||||
{
|
||||
Name = definition.Word,
|
||||
Url = definition.Permalink
|
||||
});
|
||||
eb.WithColor(new Color(239, 255, 0));
|
||||
if (!string.IsNullOrEmpty(definition.Definition)) eb.Description = description;
|
||||
if (!string.IsNullOrEmpty(definition.Example)) eb.AddField("Example", definition.Example ?? "(no example given...)");
|
||||
if (!string.IsNullOrEmpty(definition.ThumbsUp)) eb.AddInlineField("Upvotes", definition.ThumbsUp);
|
||||
if (!string.IsNullOrEmpty(definition.ThumbsDown)) eb.AddInlineField("Downvotes", definition.ThumbsDown);
|
||||
if (definitions.Tags?.Length > 0) eb.AddField("Tags", string.Join(", ", definitions.Tags));
|
||||
|
||||
await ReplyAsync("", false, eb.Build());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await _errorHandler.HandleCommandException(e, Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
112
src/Bot/Commands/Integrations/Wikipedia.cs
Normal file
112
src/Bot/Commands/Integrations/Wikipedia.cs
Normal file
|
@ -0,0 +1,112 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Geekbot.Core.Database;
|
||||
using Geekbot.Core.ErrorHandling;
|
||||
using Geekbot.Core.Extensions;
|
||||
using Geekbot.Core.WikipediaClient;
|
||||
using Geekbot.Core.WikipediaClient.Page;
|
||||
using HtmlAgilityPack;
|
||||
|
||||
namespace Geekbot.Bot.Commands.Integrations
|
||||
{
|
||||
public class Wikipedia : ModuleBase
|
||||
{
|
||||
private readonly IErrorHandler _errorHandler;
|
||||
private readonly IWikipediaClient _wikipediaClient;
|
||||
private readonly DatabaseContext _database;
|
||||
|
||||
public Wikipedia(IErrorHandler errorHandler, IWikipediaClient wikipediaClient, DatabaseContext database)
|
||||
{
|
||||
_errorHandler = errorHandler;
|
||||
_wikipediaClient = wikipediaClient;
|
||||
_database = database;
|
||||
}
|
||||
|
||||
[Command("wiki", RunMode = RunMode.Async)]
|
||||
[Summary("Get an article from wikipedia.")]
|
||||
public async Task GetPreview([Remainder] [Summary("article")] string articleName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var wikiLang = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(Context.Guild.Id.AsLong()))?.WikiLang;
|
||||
if (string.IsNullOrEmpty(wikiLang))
|
||||
{
|
||||
wikiLang = "en";
|
||||
}
|
||||
var article = await _wikipediaClient.GetPreview(articleName.Replace(" ", "_"), wikiLang);
|
||||
|
||||
if (article.Type != PageTypes.Standard)
|
||||
{
|
||||
switch (article.Type)
|
||||
{
|
||||
case PageTypes.Disambiguation:
|
||||
await ReplyAsync($"**__Disambiguation__**\r\n{DisambiguationExtractor(article.ExtractHtml)}");
|
||||
break;
|
||||
case PageTypes.MainPage:
|
||||
await ReplyAsync("The main page is not supported");
|
||||
break;
|
||||
case PageTypes.NoExtract:
|
||||
await ReplyAsync($"This page has no summary, here is the link: {article.ContentUrls.Desktop.Page}");
|
||||
break;
|
||||
case PageTypes.Standard:
|
||||
break;
|
||||
default:
|
||||
await ReplyAsync($"This page type is currently not supported, here is the link: {article.ContentUrls.Desktop.Page}");
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder
|
||||
{
|
||||
Title = article.Title,
|
||||
Description = article.Description,
|
||||
ImageUrl = article.Thumbnail?.Source.ToString(),
|
||||
Url = article.ContentUrls.Desktop.Page.ToString(),
|
||||
Color = new Color(246,246,246),
|
||||
Timestamp = article.Timestamp,
|
||||
Footer = new EmbedFooterBuilder
|
||||
{
|
||||
Text = "Last Edit",
|
||||
IconUrl = "http://icons.iconarchive.com/icons/sykonist/popular-sites/256/Wikipedia-icon.png"
|
||||
}
|
||||
};
|
||||
|
||||
eb.AddField("Description", article.Extract);
|
||||
if (article.Coordinates != null) eb.AddField("Coordinates", $"{article.Coordinates.Lat} Lat {article.Coordinates.Lon} Lon");
|
||||
await ReplyAsync("", false, eb.Build());
|
||||
}
|
||||
catch (HttpRequestException)
|
||||
{
|
||||
await ReplyAsync("I couldn't find that article");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await _errorHandler.HandleCommandException(e, Context);
|
||||
}
|
||||
}
|
||||
|
||||
private string DisambiguationExtractor(string extractHtml)
|
||||
{
|
||||
var doc = new HtmlDocument();
|
||||
doc.LoadHtml(extractHtml);
|
||||
var nodes = doc.DocumentNode.SelectNodes("//li");
|
||||
if (nodes == null) return "(List is to long to show)";
|
||||
var sb = new StringBuilder();
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
var split = node.InnerText.Split(',');
|
||||
var title = split.First();
|
||||
var desc = string.Join(",", split.Skip(1));
|
||||
sb.AppendLine($"• **{title}** -{desc}");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
58
src/Bot/Commands/Integrations/Youtube.cs
Normal file
58
src/Bot/Commands/Integrations/Youtube.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Commands;
|
||||
using Geekbot.Core.ErrorHandling;
|
||||
using Geekbot.Core.GlobalSettings;
|
||||
using Google.Apis.Services;
|
||||
using Google.Apis.YouTube.v3;
|
||||
|
||||
namespace Geekbot.Bot.Commands.Integrations
|
||||
{
|
||||
public class Youtube : ModuleBase
|
||||
{
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly IErrorHandler _errorHandler;
|
||||
|
||||
public Youtube(IGlobalSettings globalSettings, IErrorHandler errorHandler)
|
||||
{
|
||||
_globalSettings = globalSettings;
|
||||
_errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
[Command("yt", RunMode = RunMode.Async)]
|
||||
[Summary("Search for something on youtube.")]
|
||||
public async Task Yt([Remainder] [Summary("title")] string searchQuery)
|
||||
{
|
||||
var key = _globalSettings.GetKey("YoutubeKey");
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
await ReplyAsync("No youtube key set, please tell my senpai to set one");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var youtubeService = new YouTubeService(new BaseClientService.Initializer
|
||||
{
|
||||
ApiKey = key,
|
||||
ApplicationName = GetType().ToString()
|
||||
});
|
||||
|
||||
var searchListRequest = youtubeService.Search.List("snippet");
|
||||
searchListRequest.Q = searchQuery;
|
||||
searchListRequest.MaxResults = 2;
|
||||
|
||||
var searchListResponse = await searchListRequest.ExecuteAsync();
|
||||
|
||||
var result = searchListResponse.Items[0];
|
||||
|
||||
await ReplyAsync(
|
||||
$"\"{result.Snippet.Title}\" from \"{result.Snippet.ChannelTitle}\" https://youtu.be/{result.Id.VideoId}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await _errorHandler.HandleCommandException(e, Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue