Added search and lyric search functions.

Fixed playlist and current sometimes not getting results
Current now reports the elapsed/total time.
rr/dockerize
Will Hunt 7 years ago
parent 72d048b9c2
commit 18e1b2e8aa

@ -6,6 +6,8 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using MatrixSDK.Client;
using MatrixSDK.Structures;
using System.Reflection;
namespace MpdDj
{
[AttributeUsage(AttributeTargets.Method)]
@ -18,43 +20,106 @@ namespace MpdDj
}
}
[AttributeUsage(AttributeTargets.Method)]
public class BotFallback : Attribute {
}
[AttributeUsage(AttributeTargets.Method)]
public class BotHelp : Attribute {
public readonly string HelpText;
public BotHelp(string help){
HelpText = help;
}
}
public class Commands
{
[BotCmd("shuffle")]
public static void Shuffle(string cmd,string sender, MatrixRoom room){
Console.WriteLine("Shuffle");
}
//[BotCmd("shuffle")]
//public static void Shuffle(string cmd,string sender, MatrixRoom room){
// Console.WriteLine("Shuffle");
//}
[BotCmd("ping")]
[BotHelp("Ping the server and get the delay.")]
public static void Ping(string cmd, string sender, MatrixRoom room){
room.SendMessage ("pong!");
room.SendMessage ("Pong at" + DateTime.Now.ToLongTimeString());
}
[BotCmd("current")]
[BotHelp("Get the current song title.")]
public static void GetSongName(string cmd,string sender,MatrixRoom room){
MPCCurrentSong song = Program.MPCClient.CurrentSong ();
Program.MPCClient.Status();
if (song.file != null) {
FileInfo file = new FileInfo (song.file);
string name = file.Name.Replace (file.Extension, "");
name = new string(System.Text.Encoding.UTF8.GetChars (Convert.FromBase64String (name)));
room.SendMessage (name);
string[] time = Program.MPCClient.lastStatus.time.Split(':');
int elapsed = int.Parse(time[0]);
int total = int.Parse(time[1]);
name += String.Format(" {0}:{1}/{2}:{3}", elapsed/60,elapsed%60,total/60,total%60);
room.SendNotice (name);
} else {
room.SendMessage ("Nothing is currently playing");
room.SendNotice ("Nothing is currently playing");
}
}
[BotCmd("next")]
[BotHelp("Skip current song.")]
public static void NextTrack(string cmd, string sender, MatrixRoom room){
Program.MPCClient.Next ();
}
[BotCmd("help")]
[BotHelp("This help text.")]
public static void Help(string cmd, string sender, MatrixRoom room){
}
string helptext = "";
foreach(MethodInfo method in typeof(Commands).GetMethods(BindingFlags.Static|BindingFlags.Public)){
BotCmd c = method.GetCustomAttribute<BotCmd> ();
BotHelp h= method.GetCustomAttribute<BotHelp> ();
if (c != null) {
helptext += String.Format("<p><strong>{0}</strong> {1}</p>",c.CMD, h != null ? System.Web.HttpUtility.HtmlEncode(h.HelpText) : "");
}
}
MMessageCustomHTML htmlmsg = new MMessageCustomHTML();
htmlmsg.body = helptext.Replace("<strong>","").Replace("</strong>","").Replace("<p>","").Replace("</p>","\n");
htmlmsg.formatted_body = helptext;
room.SendMessage(htmlmsg);
}
[BotCmd("search")]
[BotFallback()]
[BotHelp("Get the first youtube result by keywords.")]
public static void SearchYTForTrack(string cmd, string sender, MatrixRoom room){
string query = cmd.Replace("search ","");
if(string.IsNullOrWhiteSpace(query)){
return;
}
try
{
string url = Downloaders.GetYoutubeURLFromSearch(query);
if(url != null){
DownloadTrack(url,sender,room);
}
else
{
throw new Exception("No videos matching those terms were found");
}
}
catch(Exception e){
room.SendNotice ("There was an issue with that request, "+sender+": " + e.Message);
Console.Error.WriteLine (e);
}
[BotCmd("","http://","https://","youtube.com","youtu.be","soundcloud.com")]
}
[BotCmd("[url]","http://","https://","youtube.com","youtu.be","soundcloud.com")]
[BotHelp("Type a youtube/soundcloud/file url in to add to the playlist.")]
public static void DownloadTrack(string cmd, string sender, MatrixRoom room)
{
try
@ -69,7 +134,7 @@ namespace MpdDj
}
else
{
room.SendMessage ("Sorry, that type of URL isn't supported right now :/");
room.SendNotice ("Sorry, that type of URL isn't supported right now :/");
return;
}
@ -80,22 +145,26 @@ namespace MpdDj
foreach(string[] res in videos){
Program.MPCClient.AddFile(res[0]);
}
string[] playlist = Program.MPCClient.Playlist();
//Console.WriteLine(string.Join("\n",playlist));
int position = playlist.Length-(videos.Count-1);
//ffConsole.WriteLine(position);
Program.MPCClient.Status();
#if DEBUG
Console.WriteLine(JObject.FromObject(Program.MPCClient.lastStatus));
#endif
int position = Program.MPCClient.lastStatus.playlistlength;
if(position == 1){
Program.MPCClient.Play();
room.SendMessage("Started playing " + videos[0][1] + " | " + Configuration.Config["mpc"]["streamurl"]);
room.SendNotice("Started playing " + videos[0][1] + " | " + Configuration.Config["mpc"]["streamurl"]);
}
else
{
room.SendMessage(videos[0][1] + " has been queued at position "+position+".");
room.SendNotice(videos[0][1] + " has been queued at position "+position+".");
}
}
catch(Exception e){
room.SendMessage ("There was an issue with that request, "+sender+": " + e.Message);
room.SendNotice ("There was an issue with that request, "+sender+": " + e.Message);
Console.Error.WriteLine (e);
}
}
@ -132,11 +201,34 @@ namespace MpdDj
return output;
}
[BotCmd("","stream")]
[BotCmd("stream")]
[BotHelp("Get the url of the stream.")]
public static void StreamUrl(string cmd, string sender, MatrixRoom room){
room.SendMessage(Configuration.Config["mpc"]["streamurl"]);
room.SendNotice(Configuration.Config["mpc"]["streamurl"]);
}
[BotCmd("lyrics")]
[BotHelp("Search by lyric")]
public static void LyricSearch(string cmd, string sender, MatrixRoom room){
string suggestion = Downloaders.GetSongNameByLyric(cmd.Replace("lyrics ",""));
if(suggestion == null){
room.SendNotice("I couldn't find any songs with that lyric :(");
}
else
{
room.SendNotice(String.Format("Matched '{0}'. Checking Youtube for it",suggestion));
SearchYTForTrack("search "+suggestion,sender,room);
}
}
[BotCmd("lyric")]
[BotHelp("You fear the letter 's'? Aww babe, I'll fix that for you <3")]
public static void LyricSearchAlias(string cmd, string sender, MatrixRoom room){
LyricSearch(cmd,sender,room);
}
[BotCmd("playlist")]
[BotHelp("Display the the shortened playlist.")]
public static void PlaylistDisplay(string cmd, string sender, MatrixRoom room){
string[] files = Program.MPCClient.Playlist ();
string output = "▶ ";
@ -148,13 +240,15 @@ namespace MpdDj
file = new string(System.Text.Encoding.UTF8.GetChars (Convert.FromBase64String (file)));
output += file + "\n";
}
room.SendMessage (output);
} else {
room.SendMessage ("The playlist is empty");
room.SendNotice ("The playlist is empty");
}
}
}
}

@ -5,6 +5,7 @@ using System.Net.Http;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System.Xml;
using Newtonsoft.Json.Linq;
namespace MpdDj
{
@ -18,6 +19,30 @@ namespace MpdDj
static readonly Regex YoutubePLRegex = new Regex ("^.*(youtu.be\\/|list=)([^#\\&\\?]*).*", RegexOptions.Compiled);
static readonly Regex SoundcloudRegex = new Regex ("^https?:\\/\\/(soundcloud.com|snd.sc)\\/(.*)$", RegexOptions.Compiled);
public static string GetSongNameByLyric(string lyric){
const string URL = "http://api.chartlyrics.com/apiv1.asmx/SearchLyricText?lyricText={0}";
string finalUrl = string.Format(URL,Uri.EscapeUriString(lyric));
string result = "";
using (System.Net.WebClient client = new System.Net.WebClient ()) {
result = client.DownloadString(finalUrl);
}
XmlDocument doc = new XmlDocument();
doc.LoadXml(result);
XmlElement firstSong = (XmlElement)doc.ChildNodes[1].FirstChild;
if((firstSong).GetAttribute("xsi:nil") != ""){
return null;
}
else
{
string artist = firstSong.GetElementsByTagName("Artist")[0].InnerText;
string song = firstSong.GetElementsByTagName("Song")[0].InnerText;
return string.Format("{0} {1}",artist,song);
}
}
public static void GenericDownload(string url,string filename){
string[] allowedMimetypes = Configuration.Config ["file"] ["mimetypes"].Split (' ');
using (HttpClient client = new HttpClient ()) {
@ -65,6 +90,29 @@ namespace MpdDj
}
}
public static string GetYoutubeURLFromSearch(string terms){
const string URL_FORMAT = "https://www.googleapis.com/youtube/v3/search?part=snippet&q={0}&type=video&maxResults=1&key={1}&videoCategoryId=10";
string url = string.Format(URL_FORMAT,Uri.EscapeUriString(terms),Configuration.Config["youtube"]["apikey"]);
JObject obj;
using (System.Net.WebClient client = new System.Net.WebClient ()) {
try {
string data = client.DownloadString(url);
obj = JObject.Parse(data);
} catch (Exception e) {
Console.WriteLine ("Issue with YT API", e);
throw new Exception ("Couldn't do search.");
}
}
JToken[] items = obj.GetValue("items").ToArray();
if(items.Length == 0){
return null;
}
else
{
return "https://youtube.com/watch?v=" + items[0].Value<JToken>("id").Value<string>("videoId");
}
}
public static string YoutubeGetIDFromURL(string url)
{
GroupCollection regg = YoutubeRegex.Match (url).Groups;

@ -147,7 +147,7 @@ namespace MpdDj
}
public string[] Playlist(){
string playlist = Send ("playlist");
string playlist = Send ("playlist",true);
List<string> newsongs = new List<string> ();
foreach (string song in playlist.Split ('\n')) {
int indexof = song.IndexOf (' ');
@ -159,13 +159,14 @@ namespace MpdDj
}
public void Status(){
string sstatus = Send ("status");
string sstatus = Send ("status",true);
MPCStatus status = FillStruct<MPCStatus> (sstatus);
lastStatus = status;
}
public MPCCurrentSong CurrentSong(){
string result = Send("currentsong");
string result = Send("currentsong",true);
MPCCurrentSong song = FillStruct<MPCCurrentSong>(result);
return song;
}
@ -184,8 +185,6 @@ namespace MpdDj
return foo != null ? foo.State : TcpState.Unknown;
}
}
}

@ -38,6 +38,8 @@
<HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="System.Web" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />

@ -12,6 +12,7 @@ namespace MpdDj
public static MatrixClient Client;
public static MPC MPCClient;
public static Dictionary<BotCmd,MethodInfo> Cmds = new Dictionary<BotCmd, MethodInfo>();
public static MethodInfo fallback = null;
public static void Main (string[] args)
{
Console.WriteLine ("Reading INI File");
@ -60,6 +61,12 @@ namespace MpdDj
if (cmd != null) {
Cmds.Add (cmd, method);
}
if(method.GetCustomAttribute<BotFallback>() != null){
if(fallback != null){
Console.WriteLine("WARN: You have more than one fallback command set, overwriting previous");
}
fallback = method;
}
}
}
@ -88,7 +95,10 @@ namespace MpdDj
task.Start ();
}
catch(InvalidOperationException){
//Command not found
Task task = new Task (() => {
fallback.Invoke (null, new object[3]{ msg, evt.sender, room });
});
task.Start ();
}
catch(Exception e){
Console.Error.WriteLine ("Problem with one of the commands");

Loading…
Cancel
Save