<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Curse.NET.Model;

namespace Curse.NET
{
	public class CurseClient
	{
		private readonly CurseApi curseApi = new CurseApi();
		private readonly SocketApi socketApi = new SocketApi();

		private LoginResponse login;
		private SessionResponse session;

		public event MessageReceivedEvent MessageReceived;

		public IReadOnlyList<Group> Groups { get; private set; }
		public IReadOnlyList<Friend> Friends { get; private set; }
		public IReadOnlyDictionary<string, Channel> ChannelMap { get; private set; }
		// TODO: implement this
		//public IReadOnlyDictionary<string, User> UserMap { get; private set; }
		public IReadOnlyDictionary<string, Group> GroupMap { get; private set; }

		public const string Version = "0.1.3";

		public void Connect(string username, string password)
		{
			username = WebUtility.UrlEncode(username);
			password = WebUtility.UrlEncode(password);
			login = curseApi.Post<LoginResponse>("https://logins-v1.curseapp.net/login", $"username={username}&password={password}");
			if (login.StatusMessage != null)
			{
				throw new Exception(login.StatusMessage);
			}
			if (login.Status != 1)
			{
				throw new Exception("Unable to connect");
			}
			// Connected successfully; set the API auth token
			curseApi.AuthToken = login.Session.Token;
			// Bit of a hack. Oh well.
			ModelExtensions.Api = curseApi;
			// Load server list and friends list
			LoadContacts();
			var mcfStaff = Groups.First(g => g.GroupTitle == "Minecraft Forum").Channels.First(c => c.GroupTitle == "staff-offtopic");
			var messages = mcfStaff.GetMessages(DateTime.MinValue, DateTime.Now, 30);
			// Forward socket events
			ForwardEvents();

			session = curseApi.Post<SessionResponse>("https://sessions-v1.curseapp.net/sessions", SessionRequest.Create());
			socketApi.Connect(new Uri(session.NotificationServiceUrl), login.Session.Token);
			socketApi.Login(session.MachineKey, session.SessionID, session.User.UserID);
			socketApi.Listen();
		}

		private void LoadContacts()
		{
			var contacts = curseApi.Get<ContactsRequest>("https://contacts-v1.curseapp.net/contacts");
			Groups = contacts.Groups;
			Friends = contacts.Friends;

			ChannelMap = Groups.SelectMany(g => g.Channels).ToDictionary(c => c.GroupID);
			GroupMap = Groups.ToDictionary(g => g.GroupID);
		}

		private void ForwardEvents()
		{
			socketApi.MessageReceived += message =>
			{
				var channel = ChannelMap[message.ConversationID];
				var group = GroupMap[message.ServerID];
				MessageReceived?.Invoke(group, channel, message);
			};
		}

		/// <summary>
		/// Returns the first group with the given name, or null no group with that name exist.
		/// </summary>
		public Group FindGroup(string name) => Groups.FirstOrDefault(g => g.GroupTitle == name);

		public void SendMessage(string channelId, string message)
		{
			var rs = curseApi.Post($"https://conversations-v1.curseapp.net/conversations/{channelId}", new SendMessageRequest
			{
				Body = message,
				// TODO: Verify that SessionID should be used here
				ClientID = session.SessionID,
				MachineKey = session.MachineKey
			});
		}

		public void SendMessage(Channel clientChannel, string message)
		{
			SendMessage(clientChannel.GroupID, message);
		}
	}
}<commit_msg>Fix groups being mapped incorrectly<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Curse.NET.Model;

namespace Curse.NET
{
	public class CurseClient
	{
		private readonly CurseApi curseApi = new CurseApi();
		private readonly SocketApi socketApi = new SocketApi();

		private LoginResponse login;
		private SessionResponse session;

		public event MessageReceivedEvent MessageReceived;

		public IReadOnlyList<Group> Groups { get; private set; }
		public IReadOnlyList<Friend> Friends { get; private set; }
		public IReadOnlyDictionary<string, Channel> ChannelMap { get; private set; }
		// TODO: implement this
		//public IReadOnlyDictionary<string, User> UserMap { get; private set; }
		public IReadOnlyDictionary<string, Group> GroupMap { get; private set; }

		public const string Version = "0.1.3";

		public void Connect(string username, string password)
		{
			username = WebUtility.UrlEncode(username);
			password = WebUtility.UrlEncode(password);
			login = curseApi.Post<LoginResponse>("https://logins-v1.curseapp.net/login", $"username={username}&password={password}");
			if (login.StatusMessage != null)
			{
				throw new Exception(login.StatusMessage);
			}
			if (login.Status != 1)
			{
				throw new Exception("Unable to connect");
			}
			// Connected successfully; set the API auth token
			curseApi.AuthToken = login.Session.Token;
			// Bit of a hack. Oh well.
			ModelExtensions.Api = curseApi;
			// Load server list and friends list
			LoadContacts();
			var mcfStaff = Groups.First(g => g.GroupTitle == "Minecraft Forum").Channels.First(c => c.GroupTitle == "staff-offtopic");
			var messages = mcfStaff.GetMessages(DateTime.MinValue, DateTime.Now, 30);
			// Forward socket events
			ForwardEvents();

			session = curseApi.Post<SessionResponse>("https://sessions-v1.curseapp.net/sessions", SessionRequest.Create());
			socketApi.Connect(new Uri(session.NotificationServiceUrl), login.Session.Token);
			socketApi.Login(session.MachineKey, session.SessionID, session.User.UserID);
			socketApi.Listen();
		}

		private void LoadContacts()
		{
			var contacts = curseApi.Get<ContactsRequest>("https://contacts-v1.curseapp.net/contacts");
			Groups = contacts.Groups;
			Friends = contacts.Friends;

			ChannelMap = Groups.SelectMany(g => g.Channels).ToDictionary(c => c.GroupID);
			GroupMap = Groups.ToDictionary(g => g.GroupID);
		}

		private void ForwardEvents()
		{
			socketApi.MessageReceived += message =>
			{
				var channel = ChannelMap[message.ConversationID];
				var group = GroupMap[message.RootConversationID];
				MessageReceived?.Invoke(group, channel, message);
			};
		}

		/// <summary>
		/// Returns the first group with the given name, or null no group with that name exist.
		/// </summary>
		public Group FindGroup(string name) => Groups.FirstOrDefault(g => g.GroupTitle == name);

		public void SendMessage(string channelId, string message)
		{
			var rs = curseApi.Post($"https://conversations-v1.curseapp.net/conversations/{channelId}", new SendMessageRequest
			{
				Body = message,
				// TODO: Verify that SessionID should be used here
				ClientID = session.SessionID,
				MachineKey = session.MachineKey
			});
		}

		public void SendMessage(Channel clientChannel, string message)
		{
			SendMessage(clientChannel.GroupID, message);
		}
	}
}
{'fraction_non_alphanumeric': 0.11782296650717704, 'fraction_numerical': 0.0029904306220095694, 'mean_word_length': 4.117827084927314, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 39, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4591389', 'n_tokens_mistral': 2244, 'n_tokens_neox': 1959, 'n_words': 494}