Exemplo n.º 1
0
        private async Task <YoutubeDTO> GetInfoFromYouTubeSearchAPI(string steemTitle, string steemDescription, double steemDuration, string steemAuthor)
        {
            var client = new RestClient("https://www.googleapis.com/youtube/v3/");

            var request = new RestRequest("search", Method.GET);

            request.AddQueryParameter("part", "snippet");
            request.AddQueryParameter("q", steemTitle);
            request.AddQueryParameter("type", "video");
            request.AddQueryParameter("maxResults", "1");
            request.AddQueryParameter("fields", "items(snippet(publishedAt,title,description,channelTitle,channelId),id(videoId))");
            request.AddQueryParameter("key", _configurationManager.YouTubeApiKey);

            IRestResponse response = await client.ExecuteTaskAsync(request);

            YouTubeRoot resp = JsonConvert.DeserializeObject <YouTubeRoot>(response.Content);

            if (resp == null || resp.Items.Length == 0)
            {
                return new YoutubeDTO {
                           ErrorMessage = "pas de réponse de YouTube"
                }
            }
            ;

            YouTubeSnippet video = resp.Items[0].Snippet;
            YouTubeId      id    = resp.Items[0].Id;

            // similitudes
            var    jw                  = new JaroWinkler();
            double distanceTitle       = FormatScore(jw.Similarity(steemTitle, video.Title));
            double distanceDescription = FormatScore(jw.Similarity(steemDescription, video.Description));
            double distanceAuthor      = FormatScore(jw.Similarity(steemAuthor, video.ChannelTitle));

            var dto = new YoutubeDTO
            {
                Success             = true,
                VideoId             = id.VideoId,
                VideoTitle          = video.Title,
                ChannelId           = video.ChannelId,
                ChannelTitle        = video.ChannelTitle,
                PublishedAt         = video.PublishedAt,
                DistanceTitle       = distanceTitle,
                DistanceDescription = distanceDescription,
                DistanceAuthor      = distanceAuthor
            };

            return(dto);
        }
Exemplo n.º 2
0
        public async Task <string> AnalyzeFromDiscordUserMessage(string curator, string videoMessage)
        {
            if (string.IsNullOrWhiteSpace(videoMessage))
            {
                return(curator + ": Error: Message is empty");
            }

            string url      = null;
            string warnings = "";
            bool   isVote   = false;

            if (videoMessage.StartsWith("!vote "))
            {
                url    = videoMessage.Replace("!vote ", string.Empty);
                isVote = true;
                await Console.Out.WriteLineAsync("Discord receive vote for : " + url);
            }
            else if (videoMessage.StartsWith("!downvote "))
            {
                url    = videoMessage.Replace("!downvote ", string.Empty);
                isVote = false;
                await Console.Out.WriteLineAsync("Discord receive downvote for : " + url);
            }
            else if (videoMessage.StartsWith("!cancel "))
            {
                url = videoMessage.Replace("!cancel ", string.Empty);
                await Console.Out.WriteLineAsync("Discord receive cancel for : " + url);

                if (!_dicoVote.ContainsKey(url))
                {
                    return(curator + ": Could not find any vote to cancel.");
                }

                if (_dicoVote[url].Curators.Count() > 1)
                {
                    _dicoVote[url].Curators.Remove(curator);
                    return("Ok, " + curator + ". " + _dicoVote[url].Curators.Aggregate((a, b) => a + ", " + b) + " are still voting on this video.");
                }
                _dicoVote.Remove(url);
                return("No more curator voting on " + url + " , there will be no vote.");
            }
            else
            {
                return(curator + ": Error: Unknown Command");
            }

            if (string.IsNullOrWhiteSpace(url))
            {
                return(curator + ": Error: No url found");
            }

            Tuple <string, string> tuple = null;

            if (url.StartsWith("https://d.tube/"))
            {
                tuple = ExtractAuthorAndPermLinkFromDtubeUrl(url);
            }
            else if (url.StartsWith("https://steemit.com/"))
            {
                tuple = ExtractAuthorAndPermLinkFromSteemitUrl(url);
            }

            if (tuple == null)
            {
                return(url + "\nError: URL needs to start with either d.tube or steemit.com");
            }

            SteemDTO steemInfo = GetInfoFromSteem(tuple.Item1, tuple.Item2);

            if (!steemInfo.Success)
            {
                return(url + "\nError: Could not fetch STEEM content");
            }
            if (steemInfo.DTubeVoted)
            {
                return(url + "\nError: We already voted on this video");
            }
            YoutubeDTO youtubeInfo = await GetInfoFromYouTubeSearchAPI(steemInfo.Title, steemInfo.Description, steemInfo.Duration, steemInfo.Author);

            if (!youtubeInfo.Success)
            {
                await Console.Out.WriteLineAsync("Error fetching YT for: " + url);

                warnings += "\nWarning! YT error";
                //return "Error: Could not fetch YT Content";
                //je prefere que ca ne bloque pas dans ce cas, je met un systeme de warning
            }


            // todo normalisation des scores
            // pour eviter le spaghetti temporaire suivant

            double scorePlagiat = 0;

            if (steemInfo.Description.Length < 10)
            {
                scorePlagiat = youtubeInfo.DistanceTitle;
            }
            else
            {
                scorePlagiat = (youtubeInfo.DistanceTitle + youtubeInfo.DistanceDescription) / 2;
            }
            double days      = (DateTime.Now - youtubeInfo.PublishedAt).TotalDays;
            double scoreTime = Math.Pow(0.5, days / 3.5);

            if (scorePlagiat > 0.75 && days > 7)
            {
                return(url + "\n**PLAGIARISM OR REPOST DETECTED (" + String.Format("{0:P0}", scorePlagiat) + ")**, there will be no vote.\n" + youtubeInfo.VideoUrl);
            }

            // si suspection de plaggiat
            if (scorePlagiat > 0.75 && youtubeInfo.DistanceAuthor < 0.5)
            {
                warnings += "\nWarning! Plagiarism detected (" + String.Format("{0:P0}", scorePlagiat) + ")"
                            + ", but the original is only " + Math.Round(days) + " days old. Check if it's the same author.\n";
                warnings += youtubeInfo.VideoUrl;
            }
            else if (scorePlagiat > 0.75)
            {
                warnings += "\nWarning! Looks like the same author reposting... it was reposted " + Math.Round(days) + " days later.\n";
                warnings += youtubeInfo.VideoUrl;
            }
            else if (scorePlagiat > 0.50)
            {
                warnings += "\nWarning! Possible plagiarism (" + String.Format("{0:P0}", scorePlagiat) + ")\n";
                warnings += youtubeInfo.VideoUrl;
            }

            DateTime creationDate = DateTime.SpecifyKind(steemInfo.Created, DateTimeKind.Utc);

            if (!_dicoVote.ContainsKey(url))
            {
                DateTime afterVote          = DateTime.UtcNow.AddMinutes(15);
                DateTime afterCreationVideo = creationDate.AddMinutes(30);
                DateTime voteDateTime       = afterCreationVideo > afterVote && isVote ? afterCreationVideo : afterVote; //on prend le max des 2
                _dicoVote.Add(url, new DtubeVideoDTO
                {
                    Url = url,
                    CreationDateTime = creationDate,
                    VoteDateTime     = voteDateTime,
                    Curators         = new List <string> {
                        curator
                    }
                });
            }
            else if (!_dicoVote[url].Curators.Contains(curator))
            {
                _dicoVote[url].Curators.Add(curator);
            }
            else
            {
                return(curator + ": You already voted on this video.");
            }

            DtubeVideoDTO dtubeVideoDTO = _dicoVote[url];
            TimeSpan      voteTimeSpan  = (dtubeVideoDTO.VoteDateTime - DateTime.Now.ToUniversalTime());

            if (isVote)
            {
                dtubeVideoDTO.NbUpVote++;
            }
            else
            {
                dtubeVideoDTO.NbDownVote++;
            }

            if (_dicoVote[url].Curators.Count() > 1)
            {
                warnings += "\nCurators: " + _dicoVote[url].Curators.Aggregate((a, b) => a + ", " + b);
            }

            if (dtubeVideoDTO.NbDownVote > 0 && dtubeVideoDTO.NbUpVote == 0)
            {
                return(dtubeVideoDTO.Url + " ```diff\n- Downvote in "
                       + Math.Round(voteTimeSpan.TotalMinutes) + "mins```"
                       + warnings);
            }
            if (dtubeVideoDTO.NbUpVote > 0 && dtubeVideoDTO.NbDownVote == 0)
            {
                return(dtubeVideoDTO.Url + " ```diff\n+ Vote in "
                       + Math.Round(voteTimeSpan.TotalMinutes) + "mins```"
                       + warnings);
            }

            _dicoVote.Remove(url);
            return(dtubeVideoDTO.Url + "\n**Curator disagreament**. There will be no vote");
        }