Example #1
0
        public static string GetMessage(RecentChange change, string format, string lang)
        {
            // Parse length of the diff
            string strLength = "";
            int    length    = (change.LengthNew - change.LengthOld);

            strLength = length.ToString();
            if (length > 0)
            {
                strLength = "+" + strLength;
            }
            strLength = $"({strLength})";

            if (length > 500 || length < -500)
            {
                strLength = $"**{strLength}**";
            }

            // Markdownify link
            string link = format.Replace("/wiki/$1", string.Format("/?{0}{1}", (change.OldID != 0 ? "diff=" : "oldid="), change.RevID));

            link = string.Format("([{0}]({1}))", Locale.GetMessage("eventstreams-diff", lang), link);

            // Markdownify user
            string user     = "******" + change.User;
            string talk     = "User_talk:" + change.User;
            string contribs = "Special:Contributions/" + change.User;

            user     = Linking.GetLink(user, format, true);
            talk     = Linking.GetLink(talk, format, true);
            contribs = Linking.GetLink(contribs, format, true);

            talk = string.Format("[{0}]({1})", Locale.GetMessage("eventstreams-talk", lang), talk);

            IPAddress address;

            if (IPAddress.TryParse(change.User, out address))
            {
                user = $"[{change.User}]({contribs}) ({talk})";
            }
            else
            {
                contribs = string.Format("[{0}]({1})", Locale.GetMessage("eventstreams-contribs", lang), contribs);
                user     = $"[{change.User}]({user}) ({talk} | {contribs})";
            }

            // Parse comment, adjusting for its length
            string comment = ParseComment(change.Summary, format);
            string msg     = $"{link} . . {strLength} . . {user}";

            if (msg.Length + comment.Length > 2000)
            {
                comment = ParseComment(change.Summary, format, false);
            }
            msg += comment;

            return(msg);
        }
Example #2
0
        public static DiscordEmbedBuilder GetEmbed(RecentChange change, string format, string lang)
        {
            DiscordEmbedBuilder embed = new DiscordEmbedBuilder()
                                        .WithTimestamp(change.Timestamp);

            DiscordColor embedColor = new DiscordColor(0x72777d);
            string       embedIcon  = "2/25/MobileFrontend_bytes-neutral.svg/512px-MobileFrontend_bytes-neutral.svg.png";

            // Parse statuses from the diff
            string status = "";

            if (change.Type == RecentChange.ChangeType.New)
            {
                status += Locale.GetMessage("eventstreams-new", lang);
            }
            if (change.Minor == true)
            {
                status += Locale.GetMessage("eventstreams-minor", lang);
            }

            if (status != "")
            {
                embed.WithFooter(status);
            }

            // Parse length of the diff
            int length = (change.LengthNew - change.LengthOld);

            if (length > 0)
            {
                embedColor = new DiscordColor(0x00af89);
                embedIcon  = "a/ab/MobileFrontend_bytes-added.svg/512px-MobileFrontend_bytes-added.svg.png";
            }
            else if (length < 0)
            {
                embedIcon  = "7/7c/MobileFrontend_bytes-removed.svg/512px-MobileFrontend_bytes-removed.svg.png";
                embedColor = new DiscordColor(0xdd3333);
            }

            embed
            .WithAuthor(
                change.Title,
                Linking.GetLink(change.Title, format, true),
                string.Format("https://upload.wikimedia.org/wikipedia/commons/thumb/{0}", embedIcon)
                )
            .WithColor(embedColor)
            .WithDescription(GetMessage(change, format, lang));

            return(embed);
        }
Example #3
0
        private static string ParseComment(string summary, string format, bool linkify = true)
        {
            if (summary.Length == 0)
            {
                return("");
            }

            string linkPattern     = "\\[{2}([^\\[\\]\\|\n]+)\\]{2}";
            string linkPatternPipe = "\\[{2}([^\\[\\]\\|\n]+)\\|([^\\[\\]\n]+)\\]{2}";

            // Transform code for section to simpler version
            string comment = summary.ToString().Replace("/* ", "→");

            comment = Regex.Replace(comment, " \\*/$", string.Empty).Replace(" */", ":");

            if (linkify)
            {
                // Linkify every wiki link in comment text
                comment = Regex.Replace(comment, linkPattern, m => {
                    string title = m.Groups[1].Value;
                    string link  = string.Format("[{0}]({1})", title, Linking.GetLink(title, format, true));

                    return(link);
                });

                comment = Regex.Replace(comment, linkPatternPipe, m => {
                    string title = m.Groups[1].Value;
                    string text  = m.Groups[2].Value;
                    string link  = string.Format("[{0}]({1})", text, Linking.GetLink(title, format, true));

                    return(link);
                });
            }
            else
            {
                // Display wiki links as plain text
                comment = Regex.Replace(comment, linkPattern, "$1");
                comment = Regex.Replace(comment, linkPatternPipe, "$2");
            }

            // Add italic and parentheses
            comment = $" *({comment})*";
            return(comment);
        }
Example #4
0
        public static async Task React(JToken[] list, string lang)
        {
            // List of MediaWiki/Wikimedia-related projects
            string[] twProjects = new string[]
            {
                "8",                 // MediaWiki
                "1206",              // Wikimedia
                "1238",              // Pywikibot
                "1244",              // Kiwix
                "1248",              // Huggle
                "1274",              // Phabricator
            };

            Dictionary <string, string> twNames = new Dictionary <string, string>()
            {
                { "8", "MediaWiki" },
                { "1206", "Wikimedia" },
                { "1238", "Pywikibot" },
                { "1244", "Kiwix" },
                { "1248", "Huggle" },
                { "1274", "Phabricator" },
            };

            // Filter only translations from projects above
            bool          gotToLatest = false;
            List <JToken> query       = list.Where(jt => jt.Type == JTokenType.Object).Select(item =>
            {
                string key = item["key"].ToString();
                if (twProjects.Where(x => key.StartsWith(x + ":")).ToList().Count > 0)
                {
                    // Check if matches with latest fetch
                    if (key == LatestFetchKey[lang])
                    {
                        gotToLatest = true;
                    }

                    // Return if no there is still no match
                    if (gotToLatest == false)
                    {
                        return(item);
                    }
                }

                return(null);
            }).Where(i => i != null).ToList();

            if (query.Count == 0)
            {
                return;
            }

            // Fetch every author for future message
            int count = query.Count;
            Dictionary <string, List <string> > authors = new Dictionary <string, List <string> >();
            List <string> allAuthors = new List <string>();

            foreach (var item in query)
            {
                string key        = item["key"].ToString();
                string ns         = twProjects.Where(x => key.StartsWith(x + ":")).ToList().First().ToString();
                string translator = item["properties"]["last-translator-text"].ToString();

                if (!authors.ContainsKey(ns))
                {
                    authors[ns] = new List <string>();
                }
                if (!authors[ns].Contains(translator))
                {
                    authors[ns].Add(translator);
                }
                if (!allAuthors.Contains(translator))
                {
                    allAuthors.Add(translator);
                }
            }

            // Send Discord messages to guilds
            DiscordClient client = Program.Client;

            foreach (string chan in Channels[lang])
            {
                DiscordEmbedBuilder embed = new DiscordEmbedBuilder()
                                            .WithColor(new DiscordColor(0x013467))
                                            .WithFooter("translatewiki.net");

                // Fetch info about channel
                ulong          chanId  = ulong.Parse(chan);
                DiscordChannel channel = await client.GetChannelAsync(chanId);

                string guildLang = Config.GetLang(channel.GuildId.ToString());

                // Remember the key of first message
                Config.SetInternal(channel.Id.ToString(), "translatewiki-key", query[0]["key"].ToString());

                // Inform about deadline if needed
                string deadlineInfo = null;
                if (UpdateDeadline)
                {
                    deadlineInfo       = Locale.GetMessage("translatewiki-deadline", guildLang);
                    UpdateDeadline     = false;
                    UpdateDeadlineDone = true;
                }

                // Build messages
                string headerCount = (gotToLatest ? count.ToString() : count.ToString() + "+");
                string header      = Locale.GetMessage("translatewiki-header", guildLang, headerCount, count, allAuthors.Count);
                embed.WithAuthor(
                    header,
                    string.Format("https://translatewiki.net/wiki/Special:RecentChanges?translations=only&namespace={0}&limit=500&trailer=/ru", string.Join("%3B", twProjects)),
                    "https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Translatewiki.net_logo.svg/512px-Translatewiki.net_logo.svg.png"
                    );

                // Check if authors list doesn’t exceed
                string desc = string.Join("\n", authors.Select(ns => {
                    string str = twNames[ns.Key] + ": ";
                    str       += string.Join(", ", ns.Value.Select(author =>
                    {
                        return(string.Format("[{0}]({1})", author, Linking.GetLink(author, "https://translatewiki.net/wiki/Special:Contribs/$1", true)));
                    }));

                    return(str);
                }));
                if (desc.Length > 2000)
                {
                    desc = string.Join("\n", authors.Select(ns => {
                        string str = twNames[ns.Key] + ": ";
                        str       += string.Join(", ", ns.Value.Select(author =>
                        {
                            return(author);
                        }));

                        return(str);
                    }));
                }
                embed.WithDescription(desc);

                await client.SendMessageAsync(channel, deadlineInfo, embed : embed);
            }

            // Write down new first key
            LatestFetchKey[lang] = query.First()["key"].ToString();
        }
        /// <summary>
        /// Form description of the changes for the project.
        /// </summary>
        /// <param name="authors">List of authors with their messages.</param>
        /// <returns>Changes in the project.</returns>
        private static string FormSimpleDescription(Dictionary <string, List <string> > authors)
        {
            var keys = authors.Keys.ToList();
            var list = keys.Select(author =>
            {
                return(string.Format("{0} ([{1}]({2}))", authors[author].Count, author, Linking.GetLink(author, "https://translatewiki.net/wiki/Special:Contribs/$1", true)));
            });
            string result = string.Join(", ", list);

            if (result.Length > MAX_EMBED_LENGTH)
            {
                result = string.Join(", ", keys.Select(author =>
                {
                    return($"{authors[author].Count} ({author})");
                }));
                if (result.Length > MAX_EMBED_LENGTH)
                {
                    string ellipsis = " […]";
                    result = result.Substring(0, MAX_EMBED_LENGTH - ellipsis.Length) + ellipsis;
                }
            }

            return(result);
        }
        /// <summary>
        /// Form description of the changes for the project.
        /// </summary>
        /// <param name="authors">List of authors with their messages.</param>
        /// <param name="includeIds">Whether to include message IDs in the result.</param>
        /// <returns>Changes in the project.</returns>
        private static string FormDescription(Dictionary <string, List <string> > authors, bool includeIds = true)
        {
            if (!includeIds)
            {
                return(FormSimpleDescription(authors));
            }
            Dictionary <string, string[]> storage = new Dictionary <string, string[]>();

            // Calculate how much links cost
            int authorLinkLength = 0;
            int authorNameLength = 0;

            foreach (var item in authors)
            {
                var arr = new string[3];
                arr[0] = string.Format("[{0}]({1})", item.Key, Linking.GetLink(item.Key, "https://translatewiki.net/wiki/Special:Contribs/$1", true));
                arr[1] = item.Value.Count.ToString();
                arr[2] = "";

                authorLinkLength += arr[0].Length;
                authorNameLength += item.Key.Length;
                storage.Add(item.Key, arr);
            }

            // Add as many message IDs as we can
            int  msgLength = 0;
            bool useLinks  = (authorLinkLength < (MAX_EMBED_LENGTH / 2));
            Dictionary <string, int>  msgNumbers = new Dictionary <string, int>();
            Dictionary <string, bool> finished   = new Dictionary <string, bool>();

            while (msgLength < MAX_EMBED_LENGTH)
            {
                foreach (var item in authors)
                {
                    if (msgLength > MAX_EMBED_LENGTH || item.Key == "1274")
                    {
                        break;
                    }
                    if (!msgNumbers.ContainsKey(item.Key))
                    {
                        msgNumbers[item.Key] = 0;
                    }

                    var num = msgNumbers[item.Key];
                    if (finished.ContainsKey(item.Key) || num >= item.Value.Count)
                    {
                        if (!finished.ContainsKey(item.Key))
                        {
                            finished[item.Key] = true;
                        }
                        continue;
                    }
                    ;

                    var arr = storage[item.Key];
                    if (num == 0)
                    {
                        arr[0]     = string.Format(" ({0})\n", (useLinks ? arr[0] : item.Key));
                        msgLength += arr[0].Length;
                        msgLength += arr[1].Length;
                    }

                    string str = (arr[2].Length > 0 ? ", " : "") + item.Value[num].Replace("_", @"\_");
                    if (msgLength + str.Length + arr[0].Length <= MAX_EMBED_LENGTH)
                    {
                        arr[2]    += str;
                        msgLength += str.Length;
                    }
                    else
                    {
                        finished[item.Key] = true;
                        continue;
                    }

                    msgNumbers[item.Key]++;
                }

                // Break if foreach has ended for all elements
                if (finished.Values.Select(x => x).ToList().Count == msgNumbers.Count)
                {
                    break;
                }
            }

            // Build the resulting string while accounting for unknown problems
            StringBuilder result = new StringBuilder();

            foreach (var item in storage)
            {
                int    trim    = (authors[item.Key].Count - msgNumbers[item.Key]);
                string trimmed = (trim > 0 ? $" + {trim}" : "");

                result.Append(item.Value[2]);
                result.Append(trimmed);
                if (useLinks)
                {
                    result.Append((result.Length + item.Value[0].Length > MAX_EMBED_LENGTH ? $" ({item.Key})\n" : item.Value[0]));
                }
                else
                {
                    result.Append(item.Value[0]);
                }
            }

            return(result.ToString().TrimEnd('\n'));
        }