<commit_before>﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using TweetDuck.Core.Other;

namespace TweetDuck{
    sealed class Reporter{
        private readonly string logFile;

        public Reporter(string logFile){
            this.logFile = logFile;
        }

        public void SetupUnhandledExceptionHandler(string caption){
            AppDomain.CurrentDomain.UnhandledException += (sender, args) => {
                if (args.ExceptionObject is Exception ex) {
                    HandleException(caption, "An unhandled exception has occurred.", false, ex);
                }
            };
        }

        public bool Log(string data){
            #if DEBUG
            Debug.WriteLine(data);
            #endif

            StringBuilder build = new StringBuilder();

            if (!File.Exists(logFile)){
                build.Append("Please, report all issues to: https://github.com/chylex/TweetDuck/issues\r\n\r\n");
            }

            build.Append("[").Append(DateTime.Now.ToString("G", Program.Culture)).Append("]\r\n");
            build.Append(data).Append("\r\n\r\n");

            try{
                File.AppendAllText(logFile, build.ToString(), Encoding.UTF8);
                return true;
            }catch{
                return false;
            }
        }

        public void HandleException(string caption, string message, bool canIgnore, Exception e){
            bool loggedSuccessfully = Log(e.ToString());

            FormMessage form = new FormMessage(caption, message+"\nError: "+e.Message, canIgnore ? MessageBoxIcon.Warning : MessageBoxIcon.Error);
            
            Button btnExit = form.AddButton(FormMessage.Exit);
            Button btnIgnore = form.AddButton(FormMessage.Ignore, DialogResult.Ignore, ControlType.Cancel);

            btnIgnore.Enabled = canIgnore;
            form.ActiveControl = canIgnore ? btnIgnore : btnExit;

            Button btnOpenLog = new Button{
                Anchor = AnchorStyles.Bottom | AnchorStyles.Left,
                Enabled = loggedSuccessfully,
                Font = SystemFonts.MessageBoxFont,
                Location = new Point(9, 12),
                Margin = new Padding(0, 0, 48, 0),
                Size = new Size(106, 26),
                Text = "Show Error Log",
                UseVisualStyleBackColor = true
            };

            btnOpenLog.Click += (sender, args) => {
                using(Process.Start(logFile)){}
            };

            form.AddActionControl(btnOpenLog);

            if (form.ShowDialog() == DialogResult.Ignore){
                return;
            }

            try{
                Process.GetCurrentProcess().Kill();
            }catch{
                Environment.FailFast(message, e);
            }
        }

        public static void HandleEarlyFailure(string caption, string message){
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            FormMessage.Error(caption, message, "Exit");

            try{
                Process.GetCurrentProcess().Kill();
            }catch{
                Environment.FailFast(message, new Exception(message));
            }
        }
    }
}
<commit_msg>Add exception type that adds (potentially sensitive) details to error log<commit_after>﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using TweetDuck.Core.Other;

namespace TweetDuck{
    sealed class Reporter{
        private readonly string logFile;

        public Reporter(string logFile){
            this.logFile = logFile;
        }

        public void SetupUnhandledExceptionHandler(string caption){
            AppDomain.CurrentDomain.UnhandledException += (sender, args) => {
                if (args.ExceptionObject is Exception ex) {
                    HandleException(caption, "An unhandled exception has occurred.", false, ex);
                }
            };
        }

        public bool Log(string data){
            #if DEBUG
            Debug.WriteLine(data);
            #endif

            StringBuilder build = new StringBuilder();

            if (!File.Exists(logFile)){
                build.Append("Please, report all issues to: https://github.com/chylex/TweetDuck/issues\r\n\r\n");
            }

            build.Append("[").Append(DateTime.Now.ToString("G", Program.Culture)).Append("]\r\n");
            build.Append(data).Append("\r\n\r\n");

            try{
                File.AppendAllText(logFile, build.ToString(), Encoding.UTF8);
                return true;
            }catch{
                return false;
            }
        }

        public void HandleException(string caption, string message, bool canIgnore, Exception e){
            bool loggedSuccessfully = Log(e.ToString());
            
            string exceptionText = e is ExpandedLogException ? e.Message+"\n\nDetails with potentially sensitive information are in the Error Log." : e.Message;
            FormMessage form = new FormMessage(caption, message+"\nError: "+exceptionText, canIgnore ? MessageBoxIcon.Warning : MessageBoxIcon.Error);
            
            Button btnExit = form.AddButton(FormMessage.Exit);
            Button btnIgnore = form.AddButton(FormMessage.Ignore, DialogResult.Ignore, ControlType.Cancel);

            btnIgnore.Enabled = canIgnore;
            form.ActiveControl = canIgnore ? btnIgnore : btnExit;

            Button btnOpenLog = new Button{
                Anchor = AnchorStyles.Bottom | AnchorStyles.Left,
                Enabled = loggedSuccessfully,
                Font = SystemFonts.MessageBoxFont,
                Location = new Point(9, 12),
                Margin = new Padding(0, 0, 48, 0),
                Size = new Size(106, 26),
                Text = "Show Error Log",
                UseVisualStyleBackColor = true
            };

            btnOpenLog.Click += (sender, args) => {
                using(Process.Start(logFile)){}
            };

            form.AddActionControl(btnOpenLog);

            if (form.ShowDialog() == DialogResult.Ignore){
                return;
            }

            try{
                Process.GetCurrentProcess().Kill();
            }catch{
                Environment.FailFast(message, e);
            }
        }

        public static void HandleEarlyFailure(string caption, string message){
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            FormMessage.Error(caption, message, "Exit");

            try{
                Process.GetCurrentProcess().Kill();
            }catch{
                Environment.FailFast(message, new Exception(message));
            }
        }

        public sealed class ExpandedLogException : Exception{
            private readonly string details;

            public ExpandedLogException(Exception source, string details) : base(source.Message, source){
                this.details = details;
            }

            public override string ToString() => base.ToString()+"\r\n"+details;
        }
    }
}

{'fraction_non_alphanumeric': 0.0991140642303433, 'fraction_numerical': 0.003875968992248062, 'mean_word_length': 1.810190587320109, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, 'https://': 2, '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': '1394969', 'n_tokens_mistral': 1842, 'n_tokens_neox': 1732, 'n_words': 407}