<commit_before>﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Discord
{
	public sealed class Message
	{
		public sealed class Attachment : File
		{
			/// <summary> Unique identifier for this file. </summary>
			public string Id { get; }
			/// <summary> Size, in bytes, of this file file. </summary>
			public int Size { get; }
			/// <summary> Filename of this file. </summary>
			public string Filename { get; }

			internal Attachment(string id, string url, string proxyUrl, 
				int? width, int? height, int size, string filename)
				: base(url, proxyUrl, width, height)
			{
				Id = id;
				Size = size;
				Filename = filename;
			}
		}

		public sealed class Embed
		{
			/// <summary> URL of this embed. </summary>
			public string Url { get; }
			/// <summary> Type of this embed. </summary>
			public string Type { get; }
			/// <summary> Title for this embed. </summary>
			public string Title { get; }
			/// <summary> Summary of this embed. </summary>
			public string Description { get; }
			/// <summary> Returns information about the author of this embed. </summary>
			public EmbedReference Author { get; }
			/// <summary> Returns information about the providing website of this embed. </summary>
			public EmbedReference Provider { get; }
			/// <summary> Returns the thumbnail of this embed. </summary>
			public File Thumbnail { get; }

			internal Embed(string url, string type, string title, string description, 
				EmbedReference author, EmbedReference provider, File thumbnail)
			{
				Url = url;
				Type = type;
				Title = title;
				Description = description;
				Author = author;
				Provider = provider;
				Thumbnail = thumbnail;
            }
		}

		public sealed class EmbedReference
		{
			/// <summary> URL of this embed provider. </summary>
			public string Url { get; }
			/// <summary> Name of this embed provider. </summary>
			public string Name { get; }

			internal EmbedReference(string url, string name)
			{
				Url = url;
				Name = name;
			}
		}

		public class File
		{
			/// <summary> Download url for this file. </summary>
			public string Url { get; }
			/// <summary> Preview url for this file. </summary>
			public string ProxyUrl { get; }
			/// <summary> Width of the this file, if it is an image. </summary>
			public int? Width { get; }
			/// <summary> Height of this file, if it is an image. </summary>
			public int? Height { get; }

			internal File(string url, string proxyUrl, int? width, int? height)
			{
				Url = url;
				ProxyUrl = proxyUrl;
				Width = width;
				Height = height;
			}
		}

		private readonly DiscordClient _client;
		private string _cleanText;

		/// <summary> Returns the global unique identifier for this message. </summary>
		public string Id { get; internal set; }
		/// <summary> Returns the local unique identifier for this message. </summary>
		public string Nonce { get; internal set; }

		/// <summary> Returns true if the logged-in user was mentioned. </summary>
		/// <remarks> This is not set to true if the user was mentioned with @everyone (see IsMentioningEverone). </remarks>
		public bool IsMentioningMe { get; private set; }
		/// <summary> Returns true if @everyone was mentioned by someone with permissions to do so. </summary>
		public bool IsMentioningEveryone { get; private set; }
		/// <summary> Returns true if the message was sent as text-to-speech by someone with permissions to do so. </summary>
		public bool IsTTS { get; private set; }
		/// <summary> Returns true if the message is still in the outgoing message queue. </summary>
		public bool IsQueued { get; internal set; }
		/// <summary> Returns true if the message was rejected by the server. </summary>
		public bool HasFailed { get; internal set; }
		/// <summary> Returns the raw content of this message as it was received from the server.. </summary>
		public string RawText { get; private set; }
		/// <summary> Returns the content of this message with any special references such as mentions converted. </summary>
		/// <remarks> This value is lazy loaded and only processed on first request. Each subsequent request will pull from cache. </remarks>
		public string Text => _cleanText != null ? _cleanText : (_cleanText = _client.Messages.CleanText(RawText));
		/// <summary> Returns the timestamp for when this message was sent. </summary>
		public DateTime Timestamp { get; private set; }
		/// <summary> Returns the timestamp for when this message was last edited. </summary>
		public DateTime? EditedTimestamp { get; private set; }
		/// <summary> Returns the attachments included in this message. </summary>
		public Attachment[] Attachments { get; private set; }
		private static readonly Attachment[] _initialAttachments = new Attachment[0];
		/// <summary> Returns a collection of all embeded content in this message. </summary>
		public Embed[] Embeds { get; private set; }
		private static readonly Embed[] _initialEmbeds = new Embed[0];

		private static readonly string[] _initialMentions = new string[0];
		/// <summary> Returns a collection of all user ids mentioned in this message. </summary>
		public string[] MentionIds { get; private set; }
		/// <summary> Returns a collection of all users mentioned in this message. </summary>
		[JsonIgnore]
		public IEnumerable<User> Mentions => MentionIds.Select(x => _client.Users[x]).Where(x => x != null);

		/// <summary> Returns the id of the server containing the channel this message was sent to. </summary>
		public string ServerId => Channel.ServerId;
		/// <summary> Returns the server containing the channel this message was sent to. </summary>
		[JsonIgnore]
		public Server Server => _client.Servers[Channel.ServerId];

		/// <summary> Returns the id of the channel this message was sent to. </summary>
		public string ChannelId { get; }
		/// <summary> Returns the channel this message was sent to. </summary>
		[JsonIgnore]
		public Channel Channel => _client.Channels[ChannelId];

		/// <summary> Returns true if the current user created this message. </summary>
		public bool IsAuthor => _client.CurrentUserId == UserId;
		/// <summary> Returns the id of the author of this message. </summary>
		public string UserId { get; }
		/// <summary> Returns the author of this message. </summary>
		[JsonIgnore]
		public User User => _client.Users[UserId];
		/// <summary> Returns the author of this message. </summary>
		[JsonIgnore]
		public Member Member => _client.Members[UserId, ServerId];

		internal Message(DiscordClient client, string id, string channelId, string userId)
		{
			_client = client;
			Id = id;
			ChannelId = channelId;
			UserId = userId;
			Attachments = _initialAttachments;
			Embeds = _initialEmbeds;
			MentionIds = _initialMentions;
        }

		internal void Update(API.Message model)
		{
			if (model.Attachments != null)
			{
				Attachments = model.Attachments
					.Select(x => new Attachment(x.Id, x.Url, x.ProxyUrl, x.Width, x.Height, x.Size, x.Filename))
					.ToArray();
			}
			if (model.Embeds != null)
			{<commit_msg>Throw a proper error if accessing Message.Member in a private channel.<commit_after>﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Discord
{
	public sealed class Message
	{
		public sealed class Attachment : File
		{
			/// <summary> Unique identifier for this file. </summary>
			public string Id { get; }
			/// <summary> Size, in bytes, of this file file. </summary>
			public int Size { get; }
			/// <summary> Filename of this file. </summary>
			public string Filename { get; }

			internal Attachment(string id, string url, string proxyUrl, 
				int? width, int? height, int size, string filename)
				: base(url, proxyUrl, width, height)
			{
				Id = id;
				Size = size;
				Filename = filename;
			}
		}

		public sealed class Embed
		{
			/// <summary> URL of this embed. </summary>
			public string Url { get; }
			/// <summary> Type of this embed. </summary>
			public string Type { get; }
			/// <summary> Title for this embed. </summary>
			public string Title { get; }
			/// <summary> Summary of this embed. </summary>
			public string Description { get; }
			/// <summary> Returns information about the author of this embed. </summary>
			public EmbedReference Author { get; }
			/// <summary> Returns information about the providing website of this embed. </summary>
			public EmbedReference Provider { get; }
			/// <summary> Returns the thumbnail of this embed. </summary>
			public File Thumbnail { get; }

			internal Embed(string url, string type, string title, string description, 
				EmbedReference author, EmbedReference provider, File thumbnail)
			{
				Url = url;
				Type = type;
				Title = title;
				Description = description;
				Author = author;
				Provider = provider;
				Thumbnail = thumbnail;
            }
		}

		public sealed class EmbedReference
		{
			/// <summary> URL of this embed provider. </summary>
			public string Url { get; }
			/// <summary> Name of this embed provider. </summary>
			public string Name { get; }

			internal EmbedReference(string url, string name)
			{
				Url = url;
				Name = name;
			}
		}

		public class File
		{
			/// <summary> Download url for this file. </summary>
			public string Url { get; }
			/// <summary> Preview url for this file. </summary>
			public string ProxyUrl { get; }
			/// <summary> Width of the this file, if it is an image. </summary>
			public int? Width { get; }
			/// <summary> Height of this file, if it is an image. </summary>
			public int? Height { get; }

			internal File(string url, string proxyUrl, int? width, int? height)
			{
				Url = url;
				ProxyUrl = proxyUrl;
				Width = width;
				Height = height;
			}
		}

		private readonly DiscordClient _client;
		private string _cleanText;

		/// <summary> Returns the global unique identifier for this message. </summary>
		public string Id { get; internal set; }
		/// <summary> Returns the local unique identifier for this message. </summary>
		public string Nonce { get; internal set; }

		/// <summary> Returns true if the logged-in user was mentioned. </summary>
		/// <remarks> This is not set to true if the user was mentioned with @everyone (see IsMentioningEverone). </remarks>
		public bool IsMentioningMe { get; private set; }
		/// <summary> Returns true if @everyone was mentioned by someone with permissions to do so. </summary>
		public bool IsMentioningEveryone { get; private set; }
		/// <summary> Returns true if the message was sent as text-to-speech by someone with permissions to do so. </summary>
		public bool IsTTS { get; private set; }
		/// <summary> Returns true if the message is still in the outgoing message queue. </summary>
		public bool IsQueued { get; internal set; }
		/// <summary> Returns true if the message was rejected by the server. </summary>
		public bool HasFailed { get; internal set; }
		/// <summary> Returns the raw content of this message as it was received from the server.. </summary>
		public string RawText { get; private set; }
		/// <summary> Returns the content of this message with any special references such as mentions converted. </summary>
		/// <remarks> This value is lazy loaded and only processed on first request. Each subsequent request will pull from cache. </remarks>
		public string Text => _cleanText != null ? _cleanText : (_cleanText = _client.Messages.CleanText(RawText));
		/// <summary> Returns the timestamp for when this message was sent. </summary>
		public DateTime Timestamp { get; private set; }
		/// <summary> Returns the timestamp for when this message was last edited. </summary>
		public DateTime? EditedTimestamp { get; private set; }
		/// <summary> Returns the attachments included in this message. </summary>
		public Attachment[] Attachments { get; private set; }
		private static readonly Attachment[] _initialAttachments = new Attachment[0];
		/// <summary> Returns a collection of all embeded content in this message. </summary>
		public Embed[] Embeds { get; private set; }
		private static readonly Embed[] _initialEmbeds = new Embed[0];

		private static readonly string[] _initialMentions = new string[0];
		/// <summary> Returns a collection of all user ids mentioned in this message. </summary>
		public string[] MentionIds { get; private set; }
		/// <summary> Returns a collection of all users mentioned in this message. </summary>
		[JsonIgnore]
		public IEnumerable<User> Mentions => MentionIds.Select(x => _client.Users[x]).Where(x => x != null);

		/// <summary> Returns the id of the server containing the channel this message was sent to. </summary>
		public string ServerId => Channel.ServerId;
		/// <summary> Returns the server containing the channel this message was sent to. </summary>
		[JsonIgnore]
		public Server Server => _client.Servers[Channel.ServerId];

		/// <summary> Returns the id of the channel this message was sent to. </summary>
		public string ChannelId { get; }
		/// <summary> Returns the channel this message was sent to. </summary>
		[JsonIgnore]
		public Channel Channel => _client.Channels[ChannelId];

		/// <summary> Returns true if the current user created this message. </summary>
		public bool IsAuthor => _client.CurrentUserId == UserId;
		/// <summary> Returns the id of the author of this message. </summary>
		public string UserId { get; }
		/// <summary> Returns the author of this message. </summary>
		[JsonIgnore]
		public User User => _client.Users[UserId];
		/// <summary> Returns the author of this message. </summary>
		[JsonIgnore]
		public Member Member
		{
			get
			{
				if (ServerId != null)
					return _client.Members[UserId, ServerId];
				else
					throw new InvalidOperationException("Unable to access Member in a private channel. Use User instead.");
			}
		}

		internal Message(DiscordClient client, string id, string channelId, string userId)
		{
			_client = client;
			Id = id;
			ChannelId = channelId;
			UserId = userId;
			Attachments = _initialAttachments;
			Embeds = _initialEmbeds;
			MentionIds = _initialMentions;
        }

		internal void Update(API.Message model)
		{
			if (model.Attachments != null)
			{
				Attachments = model.Attachments
					.Select(x => new Attachment(x.Id, x.Url, x.ProxyUrl, x.Width, x.Height, x.Size, x.Filename))
					.ToArray();
			}
			if (model.Embeds != null)
			{
{'fraction_non_alphanumeric': 0.10648953189121514, 'fraction_numerical': 0.0004173332405926132, 'mean_word_length': 3.195506273708783, 'pattern_counts': {'":': 0, '<': 169, '<?xml version=': 0, '>': 190, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4991041', 'n_tokens_mistral': 4548, 'n_tokens_neox': 3980, 'n_words': 1673}