public static async Task Anagram(CommandContext bc) { if (bc.MessageTokens.Length == 1) { await bc.SendReply("Syntax: !Anagram <anagram>"); return; } string query = bc.MessageTokens.Join(1); using (var clueFile = new StreamReader("Data/Clues.txt")) { string clueLine; while ((clueLine = clueFile.ReadLine()) != null) { if (!clueLine.StartsWith("Anagram", StringComparison.Ordinal)) { continue; } string[] clueTokens = clueLine.Split('|'); if (clueTokens[1].ContainsI(query)) { await bc.SendReply(@"Anagram: \c07{0}\c | NPC: \c07{1}\c | Location: \c07{2}\c", clueTokens[1], clueTokens[2], clueTokens[3]); return; } } } await bc.SendReply(@"Could not locate \c07'{0}'\c anagram.", query); }
public static async Task Remove(CommandContext bc) { if (!bc.IsAdmin) { return; } if (bc.MessageTokens.Length <= 1) { await bc.SendReply("Syntax: !RemoveTracker <rsn>"); return; } string rsn = bc.MessageTokens.Join(1).ValidatePlayerName(); var playerId = await Database.Lookup("id", "players", "rsn LIKE @name", new[] { new MySqlParameter("@name", rsn) }, -1L); if (playerId != -1) { await Database.ExecuteNonQuery("DELETE FROM tracker WHERE pid=" + playerId); await Database.ExecuteNonQuery("DELETE FROM players WHERE id=" + playerId); await bc.SendReply(@"\b{0}\b was removed from the tracker database.", rsn); } else { await bc.SendReply(@"\b{0}\b was not found on the tracker database.", rsn); } }
public static async Task WarEnd(CommandContext bc) { if (!bc.IsAdmin) { await bc.SendReply("You need to be a bot administrator to use this command."); return; } // get channel name string channelName = bc.Channel; Match matchChannel = Regex.Match(bc.Message, @"#(\S+)"); if (matchChannel.Success) { channelName = matchChannel.Groups[1].Value; bc.Message = bc.Message.Replace(matchChannel.Value, string.Empty); } var channelNameParameter = new MySqlParameter("@channelName", channelName); // get skill name var skillName = await Database.Lookup<string>("skill", "wars", "channel=@channelName", new[] { channelNameParameter }); if (skillName == null) { await bc.SendReply("You have to start a war in this channel first using !WarStart <skill>."); return; } string reply = string.Empty; var warPlayers = await Database.FetchAll("SELECT rsn FROM warPlayers WHERE channel=@channel", new MySqlParameter("@channel", channelName)); for (int count = 1; count <= warPlayers.Count; count++) { var p = await Player.FromHiscores(warPlayers[count - 1].GetString(0)); if (!p.Ranked) { await bc.SendReply(@"Player \b" + p.Name + "\b has changed his/her name or was banned during the war, and couldn't be tracked."); continue; } if (count % 2 == 0) { reply += @"\c07{0} ({1:e});\c ".FormatWith(p.Name, p.Skills[skillName]); } else { reply += "{0} ({1:e}); ".FormatWith(p.Name, p.Skills[skillName]); } if (count % 5 == 0) { await bc.SendReply(reply); reply = string.Empty; } } if (!string.IsNullOrEmpty(reply)) { await bc.SendReply(reply); } await bc.SendReply(@"\b{0}\b war ended on \u{1}\u for these players.", skillName, DateTime.UtcNow); await Database.ExecuteNonQuery("DELETE FROM wars WHERE channel='" + channelName + "'"); await Database.ExecuteNonQuery("DELETE FROM warPlayers WHERE channel='" + channelName + "'"); }
public static async Task SlayerPercent(CommandContext bc) { // get rsn string rsn; if (bc.MessageTokens.Length > 1) { rsn = await bc.GetPlayerName(bc.MessageTokens.Join(1)); } else { rsn = await bc.GetPlayerName(bc.From.Nickname); } var p = await Player.FromHiscores(rsn); if (!p.Ranked) { await bc.SendReply(@"\b{0}\b doesn't feature Hiscores.", rsn); return; } long hits_exp_gained = p.Skills[Skill.HITP].Exp - 1154; double expected_max_slayer_exp = hits_exp_gained * 3.0 / 4.0; await bc.SendReply(@"\b{0}\b \c07{1:0.##}% - {2:0.##}%\c of combat exp. is slayer based, with \c07{3:N0}\c combat slayer exp. and \c07{4:N0}\c combat total exp. (This percentage isn't accurate, mostly because of monster hp regeneration ratio and cannon slayering.)", rsn, (double) p.Skills[Skill.SLAY].Exp / expected_max_slayer_exp * 100.0, (double) p.Skills[Skill.SLAY].Exp / (expected_max_slayer_exp - ((double) hits_exp_gained / 133.0)) * 100.0, (double) p.Skills[Skill.SLAY].Exp * 16.0 / 3.0, hits_exp_gained + hits_exp_gained * 3); }
public static async Task Search(CommandContext bc) { if (bc.MessageTokens.Length == 1) { await bc.SendReply("Syntax: !MonsterSearch <search terms>"); return; } // get search terms string search_terms = bc.MessageTokens.Join(1); var results = new Monsters(search_terms); if (results.Count > 0) { var reply = @"\c12www.zybez.net\c found \c07{0}\c results:".FormatWith(results.Count); for (int i = 0; i < Math.Min(15, results.Count); i++) { reply += @" \c07{0}\c ({1});".FormatWith(results[i].Name, results[i].Level); } await bc.SendReply(reply); } else { await bc.SendReply(@"\c12www.zybez.net\c doesn't have any record for '{0}'.", search_terms); } }
public static async Task Add(CommandContext bc) { if (!bc.IsAdmin) { return; } if (bc.MessageTokens.Length <= 1) { await bc.SendReply("Syntax: !AddTracker <rsn>"); return; } string rsn = bc.MessageTokens.Join(1).ValidatePlayerName(); try { var p = await Player.FromHiscores(rsn); if (p.Ranked) { await Database.Insert("players", "rsn", rsn, "clan", string.Empty, "lastupdate", string.Empty); await p.SaveToDB(DateTime.UtcNow.ToStringI("yyyyMMdd")); await bc.SendReply(@"\b{0}\b is now being tracked.", rsn); } else { await bc.SendReply(@"\b{0}\b doesn't feature Hiscores.", rsn); } return; } catch { } await bc.SendReply(@"\b{0}\b was already being tracked.", rsn); }
public static async Task Percent(CommandContext bc) { // get rsn var rsn = await bc.GetPlayerName(bc.MessageTokens.Length > 1 ? bc.MessageTokens.Join(1) : bc.From.Nickname); var p = await Player.FromHiscores(rsn); if (!p.Ranked) { await bc.SendReply(@"\b{0}\b doesn't feature Hiscores.", rsn); return; } long totalExp = p.Skills[Skill.OVER].Exp; long combatExp = p.Skills[Skill.COMB].Exp; long f2pExp = p.Skills.F2pExp; // slayer long hits_exp_gained = p.Skills[Skill.HITP].Exp - 1154; var expected_max_slayer_exp = (int) (hits_exp_gained * 3.0 / 4.0); // pc long expected_combat_xp = p.Skills[Skill.HITP].Exp + p.Skills[Skill.HITP].Exp * 12 / 4; long current_combat_xp = p.Skills[Skill.HITP].Exp + p.Skills[Skill.ATTA].Exp + p.Skills[Skill.STRE].Exp + p.Skills[Skill.DEFE].Exp + p.Skills[Skill.RANG].Exp; await bc.SendReply(@"\b{0}\b statistic percentages | Total exp: \c07{1:N0}\c | Combat exp: \c07{2:N0}\c (\c07{3:0.##}%\c) | F2P exp: \c07{4:N0}\c (\c07{5:0.##}%\c) | Slayer%: \c07{6:0.##}% - {7:0.##}%\c | PestControl%: \c07{8:0.##}%\c", rsn, totalExp, combatExp, (double) combatExp / totalExp * 100, f2pExp, (double) f2pExp / totalExp * 100, (double) p.Skills[Skill.SLAY].Exp / expected_max_slayer_exp * 100, (double) p.Skills[Skill.SLAY].Exp / (expected_max_slayer_exp - (hits_exp_gained / 133)) * 100, (double) (current_combat_xp - expected_combat_xp) / current_combat_xp * 100); }
public static async Task Start(CommandContext bc) { // get rsn string rsn = await bc.GetPlayerName(bc.From.Nickname); var p = await Player.FromHiscores(rsn); if (!p.Ranked) { await bc.SendReply(@"\b{0}\b doesn't feature Hiscores.", rsn); return; } // get timer name string name = string.Empty; int indexOfSharp = bc.Message.IndexOf('#'); if (indexOfSharp > 0) { name = bc.Message.Substring(indexOfSharp + 1); bc.Message = bc.Message.Substring(0, indexOfSharp - 1); } // get skill string skill = Skill.OVER; if (bc.MessageTokens.Length > 1) { Skill.TryParse(bc.MessageTokens[1], ref skill); } // remove previous timer with this name, if any await Database.ExecuteNonQuery("DELETE FROM timers_exp WHERE fingerprint='" + bc.From.FingerPrint + "' AND name='" + name.Replace("'", "''") + "'"); // start a new timer with this name await Database.Insert("timers_exp", "fingerprint", bc.From.FingerPrint, "name", name, "skill", skill, "exp", p.Skills[skill].Exp.ToStringI(), "datetime", DateTime.UtcNow.ToStringI("yyyyMMddHHmmss")); await bc.SendReply(@"\b{0}\b starting exp of \c07{1:e}\c in \u{1:n}\u has been recorded{2}.", rsn, p.Skills[skill], name.Length > 0 ? @" on timer \c07" + name + @"\c" : string.Empty); }
public static async Task Set(CommandContext bc) { if (bc.MessageTokens.Length < 2) { await bc.SendReply("Syntax: !set <param> [skill] <value>"); return; } switch (bc.MessageTokens[1].ToUpperInvariant()) { case "RSN": case "NAME": await _SetName(bc); break; case "GOAL": await _SetGoal(bc); break; case "ITEM": await _SetItem(bc); break; case "SPEED": await _SetSpeed(bc); break; case "SKILL": await _SetSkill(bc); break; case "@": await _SetSkillToggle(bc); break; default: await bc.SendReply("Error: Unknown parameter."); break; } }
public static async Task Timer(CommandContext bc) { if (bc.MessageTokens.Length == 1) { int timers = 0; string reply = string.Empty; foreach (var rsTimer in await Database.FetchAll("SELECT name,duration,started FROM timers WHERE fingerprint=@fingerprint OR nick=@nick", new MySqlParameter("@fingerprint", bc.From.FingerPrint), new MySqlParameter("@nick", bc.From.Nickname))) { timers++; DateTime start = rsTimer.GetString(2).ToDateTime(); DateTime end = start.AddSeconds(rsTimer.GetDouble(1)); reply += @" \b#{0}\b timer (\c07{1}\c) ends in \c07{2}\c, at \c07{3}\c;".FormatWith(timers, rsTimer.GetString(0), (end - DateTime.UtcNow).ToLongString(), end.ToStringI("yyyy/MM/dd HH:mm:ss")); } if (timers > 0) { await bc.SendReply(@"Found \c07{0}\c timers: {1}", timers, reply); } else { await bc.SendReply("Syntax: !timer <duration>"); } return; } // get duration int duration; string name; switch (bc.MessageTokens[1].ToUpperInvariant()) { case "FARM": case "HERB": case "HERBS": duration = 75; name = bc.MessageTokens[1].ToLowerInvariant(); break; case "DAY": duration = 1440; name = bc.MessageTokens[1].ToLowerInvariant(); break; case "WEEK": case "TOG": duration = 10080; name = bc.MessageTokens[1].ToLowerInvariant(); break; default: if (!int.TryParse(bc.MessageTokens[1], out duration)) { await bc.SendReply("Error: Invalid duration. Duration must be in minutes."); return; } name = duration + " mins"; break; } // start a new timer for this duration await Database.Insert("timers", "fingerprint", bc.From.FingerPrint, "nick", bc.From.Nickname, "name", name, "duration", (duration * 60).ToStringI(), "started", DateTime.UtcNow.ToStringI("yyyyMMddHHmmss")); await bc.SendReply(@"Timer started to \b{0}\b. Timer will end at \c07{1}\c.", bc.From.Nickname, DateTime.UtcNow.AddMinutes(duration).ToStringI("yyyy/MM/dd HH:mm:ss")); }
public static async Task Event(CommandContext bc) { bool all = bc.Message.Contains("@all"); try { string eventPage = new WebClient().DownloadString("http://supremeskillers.net/api/?module=events&action=getNext"); JObject nextEvent = JObject.Parse(eventPage); if (nextEvent["data"] == null) { await bc.SendReply(@"No events currently set for Supreme Skillers. \c12http://supremeskillers.net/forum/public-events/\c"); return; } var events = new string[10]; int i = -1; foreach (JObject eventData in nextEvent["data"]) { events[++i] = eventData.ToString(); } DateTime startTime; if (!all) { nextEvent = JObject.Parse(events[0]); startTime = DateTime.ParseExact((string) nextEvent["startTime"], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); await bc.SendReply(@"Next event: \c07{0}\c starts in \c07{1}\c for more information: \c12{2}\c", nextEvent["description"], (startTime - DateTime.UtcNow).ToLongString(), nextEvent["url"]); } else { string reply = "Upcoming SS Events: "; for (i = 0; i < 10; i++) { if (events[i] == null) { break; } nextEvent = JObject.Parse(events[i]); startTime = DateTime.ParseExact((string) nextEvent["startTime"], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); if (i == 0) { reply += @"{0} (\c07{1}\c); ".FormatWith(nextEvent["description"], (startTime - DateTime.UtcNow).ToLongString()); } else { reply += @"{0} (\c07{1}\c); ".FormatWith(nextEvent["description"], string.Format("{0: dddd d MMMM}", startTime).Trim()); } } await bc.SendReply(reply.Trim()); } return; } catch { } await bc.SendReply("Error retrieving next event."); }
public static async Task ClanCheck(CommandContext bc) { if (!bc.IsAdmin) { await bc.SendReply("You need to be a bot administrator to use this command."); return; } if (bc.MessageTokens.Length == 1) { await bc.SendReply("Syntax: !ClanCheck <runehead alias>"); } // get @f2p bool f2p = false; if (bc.Message.Contains(" @f2p")) { f2p = true; bc.Message = bc.Message.Replace(" @f2p", string.Empty); } // get @p2p bool p2p = false; if (bc.Message.Contains(" @p2p")) { p2p = true; bc.Message = bc.Message.Replace(" @p2p", string.Empty); } string pageRuneHead = new WebClient().DownloadString("http://runehead.com/clans/ml.php?sort=name&clan=" + bc.MessageTokens[1]); foreach (Match clanMember in Regex.Matches(pageRuneHead, "\\?name=([^&]+)")) { var p = await Player.FromHiscores(clanMember.Groups[1].Value.ValidatePlayerName()); if (!p.Ranked) { await bc.SendReply(@"\b{0}\b is not ranked.", p.Name); continue; } if (p.Name.StartsWithI("_") || p.Name.EndsWithI("_")) { await bc.SendReply(@"\b{0}\b has unneeded underscores. Please change it to \b{1}\c.", p.Name, p.Name.Trim('_')); } if (f2p && p.Skills.F2pExp == p.Skills[Skill.OVER].Exp) { await bc.SendReply(@"\b{0}\b is \c14F2P\c.", p.Name); } if (p2p && p.Skills.F2pExp != p.Skills[Skill.OVER].Exp) { await bc.SendReply(@"\b{0}\b is \c07P2P\c.", p.Name); } } await bc.SendReply(@"Clan \b{0}\b is checked.", bc.MessageTokens[1]); }
public static async Task WarAdd(CommandContext bc) { if (!bc.IsAdmin) { await bc.SendReply("You need to be a bot administrator to use this command."); return; } if (bc.MessageTokens.Length < 2) { await bc.SendReply(@"\bSyntax:\b !WarAdd <player name> [#channel name]"); return; } // get channel name string channelName = bc.Channel; Match matchChannel = Regex.Match(bc.Message, @"#(\S+)"); if (matchChannel.Success) { channelName = matchChannel.Groups[1].Value; bc.Message = bc.Message.Replace(matchChannel.Value, string.Empty); } var channelNameParameter = new MySqlParameter("@channelName", channelName); string[] playerNames = bc.MessageTokens.Join(1).Split(new[] { ',', ';', '+', '|' }); foreach (string playerName in playerNames.Select(name => name.ValidatePlayerName())) { if (await Database.Lookup<string>("rsn", "warPlayers", "channel=@channelName", new[] { channelNameParameter }) == playerName) { await bc.SendReply(@"\b{0}\b is already signed to current war.", playerName); } else { var player = await Player.FromHiscores(playerName); if (player.Ranked) { var skillName = await Database.Lookup<string>("skill", "wars", "channel=@channelName", new[] { channelNameParameter }); if (skillName == null) { await Database.Insert("warPlayers", "channel", channelName, "rsn", playerName); } else { await Database.Insert("warPlayers", "channel", channelName, "rsn", playerName, "startLevel", player.Skills[skillName].Level.ToStringI(), "startExp", player.Skills[skillName].Exp.ToStringI(), "startRank", player.Skills[skillName].Rank.ToStringI()); } await bc.SendReply(@"\b{0}\b is now signed to current war.", playerName); await Task.Delay(1000); } else { await bc.SendReply(@"\b{0}\b doesn't feature hiscores.", playerName); } } } }
public static async Task WarStart(CommandContext bc) { if (!bc.IsAdmin) { await bc.SendReply("You need to be a bot administrator to use this command."); return; } // get channel name string channelName = bc.Channel; Match matchChannel = Regex.Match(bc.Message, @"#(\S+)"); if (matchChannel.Success) { channelName = matchChannel.Groups[1].Value; bc.Message = bc.Message.Replace(matchChannel.Value, string.Empty); } // get skill name string skillName = Skill.OVER; if (bc.MessageTokens.Length < 2 || !Skill.TryParse(bc.MessageTokens[1], ref skillName)) { await bc.SendReply(@"\bSyntax:\b !WarStart <skill name> [#channel name]"); return; } string reply = string.Empty; var warPlayers = await Database.FetchAll("SELECT rsn FROM warPlayers WHERE channel=@channel", new MySqlParameter("@channel", channelName)); for (int count = 1; count <= warPlayers.Count; count++) { var p = await Player.FromHiscores(warPlayers[count - 1].GetString(0)); await Database.Update("warPlayers", "channel='" + channelName + "' AND rsn='" + p.Name + "'", "startLevel", p.Skills[skillName].Level.ToStringI(), "startExp", p.Skills[skillName].Exp.ToStringI(), "startRank", p.Skills[skillName].Rank.ToStringI()); if (count % 2 == 0) { reply += @"\c07{0} ({1:e});\c ".FormatWith(p.Name, p.Skills[skillName]); } else { reply += "{0} ({1:e}); ".FormatWith(p.Name, p.Skills[skillName]); } if (count % 5 == 0) { await bc.SendReply(reply); reply = string.Empty; } } if (!string.IsNullOrEmpty(reply)) { await bc.SendReply(reply); } await Database.ExecuteNonQuery("DELETE FROM wars WHERE channel='" + channelName + "'"); await Database.Insert("wars", "channel", channelName, "skill", skillName, "startDate", DateTime.UtcNow.ToStringI("yyyyMMddHHmm")); await bc.SendReply(@"\b{0}\b war started on \u{1}\u for these players. \bYou can now login and good luck!\b", skillName, DateTime.UtcNow); }
public static async Task Item(CommandContext bc) { if (bc.MessageTokens.Length == 1) { await bc.SendReply("Syntax: !Item <item>"); return; } Item item; int itemId; if (int.TryParse(bc.MessageTokens[1].TrimStart('#'), out itemId)) { // !Item <id> item = new Item(itemId); } else { string query = bc.MessageTokens.Join(1); var items = new Items(query); switch (items.Count) { case 0: await bc.SendReply(@"\c12www.zybez.net\c doesn't have any record for item '{0}'.", query); return; case 1: item = items[0]; item.LoadFromWeb(); break; default: string reply = @"\c12www.zybez.net\c has \c07{0}\c items:".FormatWith(items.Count); for (int i = 0; i < Math.Min(14, items.Count); i++) { reply += @" \c07#{0}\c {1};".FormatWith(items[i].Id, items[i].Name); } if (items.Count > 14) { reply += " ..."; } await bc.SendReply(reply); return; } } if (item.Name == null) { await bc.SendReply(@"\c12www.zybez.net\c doesn't have any record for item \c07#{0}\c.", itemId); } else { await bc.SendReply(@"\c07{0}\c | Alch: \c07{1}/{2}\c | MarketPrice: \c07{3}\c | Location: \c07{4}\c | \c12www.zybez.net/item.aspx?id={5}\c", item.Name, item.HighAlch.ToShortString(1), item.LowAlch.ToShortString(1), item.MarketPrice.ToShortString(1), item.Location, item.Id); await bc.SendReply(@"Members? \c{0}\c | Quest: \c{1}\c | Tradeable? \c{2}\c | Stackable? \c{3}\c | Weight? \c07{4}Kg\c | Examine: \c07{5}\c", item.Members ? "3Yes" : "4No", string.IsNullOrEmpty(item.Quests) ? "3Yes" : "4No", item.Tradable ? "3Yes" : "4No", item.Stackable ? "3Yes" : "4No", item.Weight, item.Examine); } }
public static async Task Calc(CommandContext bc) { if (bc.MessageTokens.Length == 1) { await bc.SendReply("Syntax: !calc <expression>"); return; } var mp = new MathParser(); mp.Evaluate(bc.MessageTokens.Join(1)); await bc.SendReply(@"\c07{0}\c => \c07{1}\c", mp.Expression, mp.ValueAsString); }
public static async Task Effigies(CommandContext bc) { // .effigy <lvl> int level; if (bc.MessageTokens.Length != 2 || bc.MessageTokens[1].TryInt32(out level) == false) { await bc.SendReply("Syntax: !effigy <level>"); return; } var exp = (int) ((Math.Pow(level, 3) - 2 * Math.Pow(level, 2) + 100 * level) / 20); string reply = @"A Dragonkin Lamp used on a skill of Level \c07{0}\c will give \c07{1:N0}\c Experience.".FormatWith(level, exp); await bc.SendReply(reply); }
public static async Task WarTopAll(CommandContext bc) { if (!bc.IsAdmin) { await bc.SendReply("You need to be a bot administrator to use this command."); return; } var skill = await Database.Lookup<string>("skill", "wars", "channel=@chan", new[] { new MySqlParameter("@chan", bc.Channel) }); if (skill == null) { await bc.SendReply("There isn't a war going on in this channel."); return; } await bc.SendReply("Please wait while the bot gathers all players stats..."); // Create a list of the war players var warPlayers = new List<Player>(); foreach (var warPlayersDr in await Database.FetchAll("SELECT rsn,startrank,startlevel,startexp FROM warplayers WHERE channel=@channel", new MySqlParameter("@channel", bc.Channel))) { var warPlayer = await Player.FromHiscores(warPlayersDr.GetString(0)); if (!warPlayer.Ranked) { continue; } warPlayer.Skills[skill] -= new Skill(skill, warPlayersDr.GetInt32(1), warPlayersDr.GetInt32(2), warPlayersDr.GetInt32(3)); warPlayers.Add(warPlayer); } warPlayers = warPlayers.OrderByDescending(p => p.Skills[skill].Exp).ToList(); string reply = null; for (int i = 0; i < warPlayers.Count; i++) { if (i % 5 == 0) { if (reply != null) { await bc.SendReply(reply); } reply = @"War \u{0}\u ranking:".FormatWith(skill.ToLowerInvariant()); } reply += @" \c07#{0}\c {1} ({2:e});".FormatWith(i + 1, warPlayers[i].Name, warPlayers[i].Skills[skill]); } if (reply != null) { await bc.SendReply(reply); } }
public static async Task Check(CommandContext bc) { // get rsn string rsn = await bc.GetPlayerName(bc.From.Nickname); var p = await Player.FromHiscores(rsn); if (!p.Ranked) { await bc.SendReply(@"\b{0}\b doesn't feature Hiscores.", rsn); return; } // get timer name string name = string.Empty; int indexofsharp = bc.Message.IndexOf('#'); if (indexofsharp > 0) { name = bc.Message.Substring(indexofsharp + 1); bc.Message = bc.Message.Substring(0, indexofsharp - 1); } var rs = await Database.FetchFirst("SELECT skill,exp,datetime FROM timers_exp WHERE fingerprint=@fingerprint AND name=@name LIMIT 1", new MySqlParameter("@fingerprint", bc.From.FingerPrint), new MySqlParameter("@name", name)); if (rs != null) { string skill = rs.GetString(0); long gained_exp = p.Skills[skill].Exp - (uint) rs["exp"]; TimeSpan time = DateTime.UtcNow - rs.GetString(2).ToDateTime(); var reply = @"You gained \c07{0:N0}\c \u{1}\u exp in \c07{2}\c. That's \c07{3:N0}\c exp/h.".FormatWith(gained_exp, skill.ToLowerInvariant(), time.ToLongString(), (double) gained_exp / time.TotalHours); if (gained_exp > 0 && skill != Skill.OVER && skill != Skill.COMB && p.Skills[skill].VLevel < 126) { reply += @" Estimated time to level up: \c07{0}\c".FormatWith(TimeSpan.FromSeconds(p.Skills[skill].ExpToVLevel * time.TotalSeconds / gained_exp).ToLongString()); } await bc.SendReply(reply); } else { if (name.Length > 0) { await bc.SendReply("You must start timing a skill on that timer first."); } else { await bc.SendReply("You must start timing a skill first."); } } }
public static async Task Price(CommandContext bc) { if (bc.MessageTokens.Length == 1) { await bc.SendReply("Syntax: !Price [qty] <item>"); return; } string search_term; double qty; if (bc.MessageTokens.Length > 2 && MathParser.TryCalc(bc.MessageTokens[1], out qty)) { qty = Math.Round(qty, 1); search_term = bc.MessageTokens.Join(2); } else { qty = 1; search_term = bc.MessageTokens.Join(1); } var price_list = await Prices.FromRuneScapeSearch(search_term); if (price_list.Count == 0) { await bc.SendReply(@"\c12www.runescape.com\c doesn't have any record for '{0}'.", search_term); return; } var reply = @"\c12www.runescape.com\c found \c07{0}\c results".FormatWith(price_list.TotalItems); for (int i = 0; i < Math.Min(10, price_list.Count); i++) { reply += @" | {0}: \c07{1}\c".FormatWith(price_list[i].Name, (qty * price_list[i].MarketPrice).ToShortString(1)); if (price_list[i].ChangeToday > 0) { reply += @" \c3[+{0}]\c".FormatWith(price_list[i].ChangeToday.ToShortString(1)); } else if (price_list[i].ChangeToday < 0) { reply += @" \c4[{0}]\c".FormatWith(price_list[i].ChangeToday.ToShortString(1)); } } if (price_list.TotalItems > 10) { reply += " | (...)"; } await bc.SendReply(reply); }
public static async Task Qfc(CommandContext bc) { if (bc.MessageTokens.Length == 1) { await bc.SendReply("Syntax: !Qfc <qfc>"); return; } Match qfc = Regex.Match(bc.MessageTokens.Join(1), "(\\d+).(\\d+).(\\d+).(\\d+)"); if (!qfc.Success) { await bc.SendReply("Syntax: !Qfc <qfc>"); } else { await bc.SendReply(@"Quick find code \c07{0}-{1}-{2}-{3}\c: \c12http://forum.runescape.com/forums.ws?{0},{1},{2},{3}\c", qfc.Groups[1].Value, qfc.Groups[2].Value, qfc.Groups[3].Value, qfc.Groups[4].Value); } }
public static async Task ClanStats(CommandContext bc) { string skill = Skill.OVER; if (bc.MessageTokens.Length > 1) { Skill.TryParse(bc.MessageTokens[1], ref skill); } int totallevel = 0; long totalexp = 0; var ssplayers = await Players.FromClan("SS"); foreach (Player p in ssplayers) { totallevel += p.Skills[skill].Level; totalexp += p.Skills[skill].Exp; } await bc.SendReply(@"\bSupreme Skillers\b | Homepage: \c12http://supremeskillers.net\c | \u{0}\u average level: \c07{1}\c (\c07{2:N0}\c average exp.) | Members (\c07{3}\c): \c12http://services.runescape.com/m=clan-hiscores/members.ws?clanId=314\c", skill, totallevel / ssplayers.Count, totalexp / ssplayers.Count, ssplayers.Count); }
public static async Task Coord(CommandContext bc) { if (bc.MessageTokens.Length == 1) { await bc.SendReply("Syntax: !Coords ## ## n/s ## ## w/e"); return; } Match M = Regex.Match(bc.Message, @"(\d{1,2})\D*(\d{1,2})[^ns]*([ns])\D*(\d{1,2})\D*(\d{1,2})[^we]*([we])", RegexOptions.IgnoreCase); if (M.Success) { int lat1 = int.Parse(M.Groups[1].Value, CultureInfo.InvariantCulture); int lat2 = int.Parse(M.Groups[2].Value, CultureInfo.InvariantCulture); char lat = char.ToUpperInvariant(M.Groups[3].Value[0]); int lon1 = int.Parse(M.Groups[4].Value, CultureInfo.InvariantCulture); int lon2 = int.Parse(M.Groups[5].Value, CultureInfo.InvariantCulture); char lon = char.ToUpperInvariant(M.Groups[6].Value[0]); using (var clueFile = new StreamReader("Data/Clues.txt")) { string clueLine; while ((clueLine = clueFile.ReadLine()) != null) { if (!clueLine.StartsWith("Coords", StringComparison.Ordinal)) { continue; } string[] clueTokens = clueLine.Split('|'); if (int.Parse(clueTokens[1].Substring(0, 2), CultureInfo.InvariantCulture) == lat1 && int.Parse(clueTokens[1].Substring(2, 2), CultureInfo.InvariantCulture) == lat2 && clueTokens[1][4] == lat && int.Parse(clueTokens[1].Substring(5, 2), CultureInfo.InvariantCulture) == lon1 && int.Parse(clueTokens[1].Substring(7, 2), CultureInfo.InvariantCulture) == lon2 && clueTokens[1][9] == lon) { await bc.SendReply(@"Lat: \c07{0}º{1}'{2}\c | Lon: \c07{3}º{4}'{5}\c | Location: \c07{6}\c (\c12http://www.tip.it/runescape/img2/{0:00}_{1:00}{2}_{3:00}_{4:00}{5}.gif\c)", lat1, lat2, lat.ToStringI().ToUpperInvariant(), lon1, lon2, lon.ToStringI().ToUpperInvariant(), clueTokens[2]); return; } } } await bc.SendReply(@"Could not locate \c07{0}º{1}'{2}\c / \c07{3}º{4}'{5}\c.", lat1, lat2, lat, lon1, lon2, lon); } else { await bc.SendReply("Syntax: !Coords ## ## n/s ## ## w/e"); } }
public static async Task Graph(CommandContext bc) { string skill = Skill.OVER; string rsn = await bc.GetPlayerName(bc.From.Nickname); if (bc.MessageTokens.Length > 1) { if (Skill.TryParse(bc.MessageTokens[1], ref skill)) { if (bc.MessageTokens.Length > 2) { rsn = await bc.GetPlayerName(bc.MessageTokens.Join(2)); } } else { rsn = await bc.GetPlayerName(bc.MessageTokens.Join(1)); } } await bc.SendReply(@"\b{0}\b \c07{1}\c graph | level: \c12http://t.rscript.org/graph-{0}.{2}.lvl.png\c | exp: \c12http://t.rscript.org/graph-{0}.{2}.png\c | rank: \c12http://t.rscript.org/graph-{0}.{2}.rank.png\c", rsn, skill.ToLowerInvariant(), Skill.NameToId(skill)); }
public static async Task ClanInfo(CommandContext bc) { if (bc.MessageTokens.Length == 1) { await bc.SendReply("Syntax: !ClanInfo <clan name|clan initials>"); } // Get the clan to lookup string query = bc.MessageTokens.Join(1); try { string pageClans = new WebClient().DownloadString("http://runehead.com/feeds/lowtech/searchclan.php?type=2&search=" + query); List<string[]> clans = pageClans.Split('\n').Select(clan => clan.Split('|')).Where(clanInfo => clanInfo.Length == 16).ToArray().ToList(); // order by overall, make sure ss gets the top spot :p try { clans.Sort((c1, c2) => -int.Parse(c1[8]).CompareTo(int.Parse(c2[8]))); } catch { } if (clans.Count > 0) { await bc.SendReply(@"[\c07{0}\c] \c07{1}\c (\c12{2}\c) | Members: \c07{3}\c | Avg: Cmb: (F2P: \c07{4}\c | P2P: \c07{5}\c) Hp: \c07{6}\c Magic: \c07{7}\c Ranged: \c07{8}\c Skill Total: \c07{9}\c | \c07{10}\c based (Homeworld \c07{11}\c) | Cape: \c07{12}\c | RuneHead: \c12{13}\c", clans[0][4], clans[0][0], clans[0][1], clans[0][5], clans[0][15], clans[0][6], clans[0][7], clans[0][9], clans[0][10], clans[0][8], clans[0][11], clans[0][14], clans[0][13], clans[0][2]); } else { await bc.SendReply(@"\c12www.runehead.com\c doesn't have any record for \b{0}\b.", query); } return; } catch { } await bc.SendReply(@"\c12www.runehead.com\c seems to be down."); }
private static async Task _SetName(CommandContext bc) { if (bc.MessageTokens.Length < 3) { await bc.SendReply("Syntax: !set name <rsn>"); return; } string rsn = bc.MessageTokens.Join(2).ValidatePlayerName(); // add/update to database if (await Database.Lookup<long>("COUNT(*)", "users", "fingerprint=@fp", new[] { new MySqlParameter("@fp", bc.From.FingerPrint) }) > 0) { await Database.Update("users", "fingerprint='" + bc.From.FingerPrint + "'", "rsn", rsn); } else { await Database.Insert("users", "fingerprint", bc.From.FingerPrint, "rsn", rsn); } await bc.SendReply(@"Your default RuneScape name is now \b{0}\b. This RSN is associated with the address \u*!*{1}\u.", rsn, bc.From.FingerPrint); }
public static async Task F2pPercent(CommandContext bc) { // get rsn string rsn; if (bc.MessageTokens.Length > 1) { rsn = await bc.GetPlayerName(bc.MessageTokens.Join(1)); } else { rsn = await bc.GetPlayerName(bc.From.Nickname); } var p = await Player.FromHiscores(rsn); if (!p.Ranked) { await bc.SendReply(@"\b{0}\b doesn't feature Hiscores.", rsn); return; } await bc.SendReply(@"\b{0}\b is \c07{1:0.##}%\c f2p based, with \c07{2:N0}\c f2p based exp. and \c07{3:e}\c total exp.", rsn, (double) p.Skills.F2pExp / (double) p.Skills[Skill.OVER].Exp * 100, p.Skills.F2pExp, p.Skills[Skill.OVER]); }
public static async Task WarRemove(CommandContext bc) { if (!bc.IsAdmin) { await bc.SendReply("You need to be a bot administrator to use this command."); return; } if (bc.MessageTokens.Length < 2) { await bc.SendReply(@"\bSyntax:\b !WarRemove <player name> [#channel name]"); return; } // get channel name string channelName = bc.Channel; Match matchChannel = Regex.Match(bc.Message, @"#(\S+)"); if (matchChannel.Success) { channelName = matchChannel.Groups[1].Value; bc.Message = bc.Message.Replace(matchChannel.Value, string.Empty); } var channelNameParameter = new MySqlParameter("@channelName", channelName); string playerName = bc.MessageTokens.Join(1).ValidatePlayerName(); var playerNameParameter = new MySqlParameter("@playerName", playerName); if (await Database.Lookup<string>("rsn", "warPlayers", "channel=@channelName AND rsn=@playerName", new[] { channelNameParameter, playerNameParameter }) != null) { await Database.ExecuteNonQuery("DELETE FROM warPlayers WHERE channel='" + channelName + "' AND rsn='" + playerName + "'"); await bc.SendReply(@"\b{0}\b was removed from current war.", playerName); } else { await bc.SendReply(@"\b{0}\b isn't signed to current war.", playerName); } }
public static async Task Top(CommandContext bc) { string rsn; string skill = null, activity = null; int rank; // get @level bool level = false; if (bc.Message.Contains(" @level") || bc.Message.Contains(" @lvl") || bc.Message.Contains(" @l")) { level = true; bc.Message = bc.Message.Replace(" @level", string.Empty); bc.Message = bc.Message.Replace(" @lvl", string.Empty); bc.Message = bc.Message.Replace(" @l", string.Empty); } // Parse command arguments if (bc.MessageTokens.Length == 1) { // !Top rank = 1; skill = Skill.OVER; } else if (Bot.Activity.TryParse(bc.MessageTokens[1], ref activity) || Skill.TryParse(bc.MessageTokens[1], ref skill)) { // !Top Skill/Activity rank = 1; if (bc.MessageTokens.Length > 2) { if (int.TryParse(bc.MessageTokens[2], out rank)) { // !Top Skill/Activity Rank } else { // !Top Skill/Activity RSN rsn = await bc.GetPlayerName(bc.MessageTokens.Join(2)); var p = await Player.FromHiscores(rsn); if (p.Ranked) { if (skill == null) { rank = p.Activities[activity].Rank; } else { rank = p.Skills[skill].Rank; } } } } } else if (int.TryParse(bc.MessageTokens[1], out rank)) { // !Top Rank skill = Skill.OVER; } else { // !Top RSN rank = 1; skill = Skill.OVER; rsn = await bc.GetPlayerName(bc.MessageTokens.Join(1)); var p = await Player.FromHiscores(rsn); if (p.Ranked) { rank = p.Skills[skill].Rank; } } if (rank < 0) { rank = 1; } var hiscores = new Hiscores(skill, activity, rank); int startIndex = Math.Max(rank - hiscores[0].Rank - 5, 0); var reply = @"RS \u{0}\u rankings:".FormatWith(hiscores.Name.ToLowerInvariant()); if (activity == null) { for (int i = startIndex; i < Math.Min(startIndex + 12, hiscores.Count); i++) { reply += " "; if (hiscores[i].Rank == rank) { reply += @"\b"; } if (level) { reply += @"\c07#{0:r}\c {1} ({0:l})".FormatWith((Skill) hiscores[i], hiscores[i].RSN); } else { reply += @"\c07#{0:r}\c {1} ({0:e})".FormatWith((Skill) hiscores[i], hiscores[i].RSN); } if (hiscores[i].Rank == rank) { reply += @"\b"; } reply += ";"; } } else { for (int i = startIndex; i < Math.Min(12, hiscores.Count); i++) { reply += " "; if (hiscores[i].Rank == rank) { reply += @"\b"; } reply += @"\c07#{0}\c {1} ({2})".FormatWith(hiscores[i].Rank, hiscores[i].RSN, ((Activity) hiscores[i]).Score); if (hiscores[i].Rank == rank) { reply += @"\b"; } reply += ";"; } } await bc.SendReply(reply); }
public static async Task Track(CommandContext bc) { // get time int intervalTime = 604800; string intervalName = "1 week"; Match interval = Regex.Match(bc.Message, @"@(\d+)?(second|minute|month|hour|week|year|sec|min|day|s|m|h|d|w|y)s?", RegexOptions.IgnoreCase); if (interval.Success) { if (interval.Groups[1].Value.Length > 0) { intervalTime = int.Parse(interval.Groups[1].Value, CultureInfo.InvariantCulture); } else { intervalTime = 1; } if (intervalTime < 1) { intervalTime = 1; } switch (interval.Groups[2].Value) { case "second": case "sec": case "s": intervalName = intervalTime + " second" + (intervalTime == 1 ? string.Empty : "s"); break; case "minute": case "min": case "m": intervalName = intervalTime + " minute" + (intervalTime == 1 ? string.Empty : "s"); intervalTime *= 60; break; case "hour": case "h": intervalName = intervalTime + " hour" + (intervalTime == 1 ? string.Empty : "s"); intervalTime *= 3600; break; case "day": case "d": intervalName = intervalTime + " day" + (intervalTime == 1 ? string.Empty : "s"); intervalTime *= 86400; break; case "week": case "w": intervalName = intervalTime + " week" + (intervalTime == 1 ? string.Empty : "s"); intervalTime *= 604800; break; case "month": intervalName = intervalTime + " month" + (intervalTime == 1 ? string.Empty : "s"); intervalTime *= 2629746; break; case "year": case "y": intervalName = intervalTime + " year" + (intervalTime == 1 ? string.Empty : "s"); intervalTime *= 31556952; break; } bc.Message = Regex.Replace(bc.Message, @"@(\d+)?(second|minute|month|hour|week|year|sec|min|day|s|m|h|d|w|y)s?", string.Empty, RegexOptions.IgnoreCase); bc.Message = bc.Message.Trim(); } intervalName = "last " + intervalName; // get rsn string rsn; if (bc.MessageTokens.Length > 1) { rsn = await bc.GetPlayerName(bc.MessageTokens.Join(1)); } else { rsn = await bc.GetPlayerName(bc.From.Nickname); } // Get new player var PlayerNew = await Player.FromHiscores(rsn); if (!PlayerNew.Ranked) { await bc.SendReply(@"\b{0}\b doesn't feature Hiscores.", rsn); return; } // Get old player var PlayerOld = new Player(rsn, intervalTime); if (!PlayerOld.Ranked) { await bc.SendReply(@"\b{0}\b wasn't being tracked on {1}.", rsn, DateTime.UtcNow.AddSeconds(-intervalTime).ToStringI("yyyy-MMM-dd")); return; } // 1st line: overall / combat string ReplyMsg = @"\b{0}\b \u{1}\u skills:".FormatWith(rsn, intervalName); Skill OverallDif = PlayerNew.Skills[Skill.OVER] - PlayerOld.Skills[Skill.OVER]; if (OverallDif.Exp <= 0) { await bc.SendReply(@"No performance for \b{0}\b within this period.", rsn); } else { Skill CombatDif = PlayerNew.Skills[Skill.COMB] - PlayerOld.Skills[Skill.COMB]; string DifLevel = string.Empty; if (OverallDif.Level > 0) { DifLevel = @" [\b+{0}\b]".FormatWith(OverallDif.Level); } ReplyMsg += @" \c07Overall\c lvl {0} \c3+{1}\c xp (Avg. hourly exp.: \c07{2}\c)".FormatWith(PlayerNew.Skills[Skill.OVER].Level + DifLevel, OverallDif.Exp.ToShortString(1), (OverallDif.Exp / (intervalTime / 3600.0)).ToShortString(0)); DifLevel = string.Empty; if (CombatDif.Level > 0) { DifLevel = @" [\b+{0}\b]".FormatWith(CombatDif.Level); } ReplyMsg += @"; \c7Combat\c lvl {0} \c03+{1}\c xp (\c07{2}%\c)".FormatWith(PlayerNew.Skills[Skill.COMB].Level + DifLevel, CombatDif.Exp.ToShortString(1), (CombatDif.Exp / (double) OverallDif.Exp * 100.0).ToShortString(1)); await bc.SendReply(ReplyMsg); // 2nd line: skills list List<Skill> SkillsDif = (from SkillNow in PlayerNew.Skills.Values where SkillNow.Name != Skill.OVER && SkillNow.Name != Skill.COMB select SkillNow - PlayerOld.Skills[SkillNow.Name]).ToList(); SkillsDif.Sort(); ReplyMsg = @"\b{0}\b \u{1}\u skills:".FormatWith(rsn, intervalName); for (int i = 0; i < 10; i++) { if (SkillsDif[i].Exp > 0) { DifLevel = string.Empty; if (SkillsDif[i].Level > 0) { DifLevel = @" [\b+{0}\b]".FormatWith(SkillsDif[i].Level); } ReplyMsg += @" \c07{0}\c lvl {1} \c3+{2}\c xp;".FormatWith(SkillsDif[i].Name, PlayerNew.Skills[SkillsDif[i].Name].Level + DifLevel, SkillsDif[i].Exp.ToShortString(1)); } } await bc.SendReply(ReplyMsg); } }