PageRenderTime 1ms CodeModel.GetById 2ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/wormy/Modules/YouTubeModule.cs

https://gitlab.com/SirCmpwn/wormy
C# | 174 lines | 164 code | 9 blank | 1 comment | 40 complexity | ca6401689410b452369c81f4272a006b MD5 | raw file
  1using System;
  2using System.Net;
  3using System.IO;
  4using System.Xml.Linq;
  5using System.Linq;
  6using System.Globalization;
  7using ChatSharp.Events;
  8using System.Threading.Tasks;
  9using Newtonsoft.Json.Linq;
 10using System.Xml;
 11
 12namespace wormy.Modules
 13{
 14    // TODO: Add some stuff to ChatSharp to make formatting colored messages less painful
 15    [Depends(typeof(GoogleModule))]
 16    [Depends(typeof(LinksModule))]
 17    public class YouTubeModule : Module
 18    {
 19        public override string Name { get { return "youtube"; } }
 20        public override string Description { get { return "Searches YouTube videos and handles YouTube links."; } }
 21
 22        public YouTubeModule(NetworkManager network) : base(network)
 23        {
 24            if (string.IsNullOrEmpty(Program.Configuration.GoogleAPIKey))
 25                return;
 26            RegisterUserCommand("youtube", HandleCommand, "youtube [terms]: Searches YouTube for [terms] and shows information about the first result.");
 27            RegisterUserCommand("yt", HandleCommand);
 28            network.ModulesLoaded += (sender, e) => GetModule<LinksModule>().RegisterHostHandler("www.youtube.com", HandleLink);
 29            network.ModulesLoaded += (sender, e) => GetModule<LinksModule>().RegisterHostHandler("youtube.com", HandleLink);
 30            network.ModulesLoaded += (sender, e) => GetModule<LinksModule>().RegisterHostHandler("youtu.be", HandleLink);
 31        }
 32
 33        void HandleLink(Uri uri, PrivateMessageEventArgs e)
 34        {
 35            HandleCommand(new[] { uri.ToString() }, e);
 36        }
 37
 38        void HandleCommand(string[] arguments, PrivateMessageEventArgs e)
 39        {
 40            Task.Factory.StartNew(() =>
 41                {
 42                    if (arguments.Length == 0)
 43                        return;
 44                    string vid;
 45                    if (arguments.Length != 1 || (!arguments[0].StartsWith("http://") && !arguments[0].StartsWith("https://")))
 46                    {
 47                        var results = GoogleModule.DoGoogleSearch("site:youtube.com " + string.Join(" ", arguments));
 48                        if (results.Count == 0)
 49                        {
 50                            Respond(e, "No results found.");
 51                            return;
 52                        }
 53                        else
 54                            vid = results.First().Substring(results.First().LastIndexOf("http://"));
 55                    }
 56                    else
 57                        vid = arguments[0];
 58                    if (!vid.StartsWith("http://") && !vid.StartsWith("https://"))
 59                        vid = "http://" + vid;
 60                    if (Uri.IsWellFormedUriString(vid, UriKind.Absolute))
 61                    {
 62                        Uri uri = new Uri(vid);
 63                        if (uri.Host == "youtu.be" || uri.Host == "www.youtu.be")
 64                            vid = uri.LocalPath.Trim('/');
 65                        else
 66                        {
 67                            var query = System.Web.HttpUtility.ParseQueryString(uri.Query);
 68                            vid = query["v"];
 69                        }
 70                        if (vid == null)
 71                        {
 72                            Respond(e, "Video not found.");
 73                            return;
 74                        }
 75                    }
 76                    var video = GetYoutubeVideo(vid);
 77                    if (video == null)
 78                    {
 79                        Respond(e, "Video not found.");
 80                        return;
 81                    }
 82                    string partOne = "\"\u0002" + video.Title + "\u000f\" [" + video.Duration.ToString("m\\:ss")
 83                             + "] (\u000312" + video.Author + "\u000f)\u000303 " + (video.HD ? "HD" : "SD");
 84                    string partTwo = video.Views.ToString("N0", CultureInfo.InvariantCulture) + " views";
 85                    if (video.RatingsEnabled)
 86                    {
 87                        partTwo += ", " + "(+\u000303" + video.Likes.ToString("N0", CultureInfo.InvariantCulture)
 88                        + "\u000f|-\u000304" + video.Dislikes.ToString("N0", CultureInfo.InvariantCulture) + "\u000f) [" + video.Stars + "]";
 89                    }
 90                    if (video.RegionLocked | !video.CommentsEnabled || !video.RatingsEnabled)
 91                    {
 92                        partTwo += " ";
 93                        if (video.RegionLocked)
 94                            partTwo += "\u000304Region locked\u000f, ";
 95                        if (!video.CommentsEnabled)
 96                            partTwo += "\u000304Comments disabled\u000f, ";
 97                        if (!video.RatingsEnabled)
 98                            partTwo += "\u000304Ratings disabled\u000f, ";
 99                        partTwo = partTwo.Remove(partTwo.Length - 3);
100                    }
101                    if (partOne.Length < partTwo.Length)
102                        partOne += "\u000f " + video.VideoUri.ToString();
103                    else
104                        partTwo += "\u000f " + video.VideoUri.ToString();
105                    Respond(e, partOne);
106                    Respond(e, partTwo);
107                });
108        }
109
110        class Video
111        {
112            public string Title, Author;
113            public int Views, Likes, Dislikes;
114            public TimeSpan Duration;
115            public bool RegionLocked, HD, CommentsEnabled, RatingsEnabled;
116            public string Stars;
117            public Uri VideoUri;
118        }
119
120        private Video GetYoutubeVideo(string vid)
121        {
122            try
123            {
124                WebClient client = new WebClient();
125                var sr = new StreamReader(client.OpenRead(string.Format(
126                    "https://www.googleapis.com/youtube/v3/videos?part=id%2Csnippet%2Cstatistics%2CcontentDetails%2Cstatus%2Clocalizations&id={0}&key={1}",
127                    Uri.EscapeUriString(vid), Uri.EscapeUriString(Program.Configuration.GoogleAPIKey))));
128                string json = sr.ReadToEnd();
129                JObject j = JObject.Parse(json);
130                if (j["items"].Count() == 0)
131                    return null;
132                dynamic i = j["items"][0];
133
134                Video video = new Video();
135                video.Title = i.snippet.title;
136                video.Author = i.snippet.channelTitle;
137
138                video.CommentsEnabled = true; // NOTE: YouTube has removed this from their API, assholes
139                video.RatingsEnabled = i.status.publicStatsViewable;
140                if (video.RatingsEnabled)
141                {
142                    video.Likes = i.statistics.likeCount;
143                    video.Dislikes = i.statistics.dislikeCount;
144                    double average;
145                    if (video.Likes + video.Dislikes == 0) average = 1;
146                    else average = (double)video.Likes / (video.Likes + video.Dislikes);
147                    video.Stars = "\u000303";
148                    int starCount = (int)Math.Round(average * 5);
149                    for (int k = 0; k < 5; k++)
150                    {
151                        if (k < starCount)
152                            video.Stars += "★";
153                        else if (k == starCount)
154                            video.Stars += "\u000315☆";
155                        else
156                            video.Stars += "☆";
157                    }
158                    video.Stars += "\u000f";
159                }
160                video.Views = i.statistics.viewCount;
161                video.Duration = XmlConvert.ToTimeSpan(i["contentDetails"]["duration"].Value);
162                video.RegionLocked = i.contentDetails["regionRestriction"] != null;
163                video.VideoUri = new Uri("http://youtu.be/" + vid);
164                video.HD = i.contentDetails.definition == "hd";
165                return video;
166            }
167            catch
168            {
169                return null;
170            }
171        }
172    }
173}
174