Пример #1
0
        private static void ProcessPulses(object sender, ElapsedEventArgs e)
        {
            Task.Run(() =>
            {
                try
                {
                    if (pulseQueue != null && ((currentPulse != null && !currentPulse.isEmpty()) || !pulseQueue.IsEmpty) && EnoughTimePassed(DateTime.Now))
                    {
                        if (currentPulse != null && !currentPulse.isEmpty())
                        {
                            pulseQueue.Enqueue(currentPulse);
                            currentPulse = new Pulse();
                            currentCount = 0;
                        }

                        // run only if the task didn't run yet, or the previous one already finished
                        if (pulseProcessor == null || pulseProcessor.IsCompleted || pulseProcessor.IsFaulted) // don't start if it's cancelled
                        {
                            try
                            {
                                pulseProcessor = ProcessPulses(pulseProcessor_tokensource);
                            }
                            catch (OperationCanceledException) {}
                        }
                        //ProcessPulses();
                    }

                    UpdateStatusbar();
                }
                catch (Exception ex)
                {
                    Logger.Error("Error processing pulses", ex);
                }
            });
        }
        internal static void PluginCleanUp()
        {
            try
            {
                nppStarted = false;

                Logger.Debug("Cancelling pulses...");

                // Flush the current pulse
                if (pulseQueue != null && currentPulse != null && !currentPulse.IsEmpty())
                {
                    pulseQueue.Enqueue(currentPulse);
                    currentPulse = new Pulse();
                    currentCount = 0;
                }

                pulseProcessor_tokensource.Cancel();

                if (timer != null)
                {
                    timer.Stop();
                    timer.Elapsed -= ProcessPulses;
                    timer.Dispose();
                    timer = null;

                    // make sure the queue is empty
                    //ProcessPulses();
                }

                // test if we can cancel and dump pulses
                JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
                if (pulseProcessor == null)
                {
                    Logger.Info("pulseProcessor.wait() would fail, as pulseProcessor is null");
                }
                else
                {
                    Logger.Info("calling pulseProcessor.Wait()");
                    pulseProcessor.Wait();
                }
                while (pulseQueue.TryDequeue(out Pulse result))
                {
                    if (!result.IsEmpty())
                    {
                        string json = jsonSerializer.Serialize(result);
                        Logger.Debug("Unsaved pulse: " + json);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("error on plugincleanup", ex);
            }
        }
Пример #3
0
        internal static void PluginCleanUp()
        {
            nppStarted = false;

            Logger.Debug("Cancelling pulses...");

            // Flush the current pulse
            if (pulseQueue != null && currentPulse != null && !currentPulse.isEmpty())
            {
                pulseQueue.Enqueue(currentPulse);
                currentPulse = new Pulse();
                currentCount = 0;
            }

            pulseProcessor_tokensource.Cancel();

            if (timer != null)
            {
                timer.Stop();
                timer.Elapsed -= ProcessPulses;
                timer.Dispose();
                timer = null;

                // make sure the queue is empty
                //ProcessPulses();
            }

            // test if we can cancel and dump pulses
            var jsonSerializer = new JavaScriptSerializer();

            pulseProcessor.Wait();
            Pulse result;

            while (pulseQueue.TryDequeue(out result))
            {
                if (!result.isEmpty())
                {
                    string json = jsonSerializer.Serialize(result);
                    Logger.Debug("Unsaved pulse: " + json);
                }
            }
        }
Пример #4
0
        private static void InitializeAsync()
        {
            if (System.Net.ServicePointManager.SecurityProtocol != 0)
            {
                // If the value is not set to 0 (SystemDefault), disable old protocols and make sure TLS 1.3, 1.2, 1.1 are enabled
                System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
                System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Tls;
                System.Net.ServicePointManager.SecurityProtocol |= (SecurityProtocolType)12288 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
            }
            //System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)0; // SystemDefault, we don't use this since it's supported only since .NET 4.7

            //Updater.RenameTest();
            //Updater.SignatureVerificationTest();
            try
            {
                // Delete existing log file to save space
                Logger.Delete();
            }
            catch { }

            Logger.Info(string.Format("Initializing Code::Stats v{0}", Constants.PluginVersion));

            try
            {
                currentPulse = new Pulse();

                Logger.Info("Initialing settings form...");
                // Settings Form
                _settingsForm              = new CodeStats.Forms.SettingsForm();
                _settingsForm.ConfigSaved += SettingsFormOnConfigSaved;
                Logger.Info("Initialized settings form"); // it takes 5 seconds to get here from Initializing Code::Stats message...

                // Load config file
                _CodeStatsConfigFile = new ConfigFile();
                GetSettings(true);

                Logger.Debug("Loaded config");

                LoadExtensionMapping();

                // Check for updates
                Task.Run(() =>
                {
                    try
                    {
                        string latest = Constants.LatestPluginVersion();
                        if (Constants.PluginVersion != latest && !String.IsNullOrWhiteSpace(latest))
                        {
                            MessageBox.Show("There is Code::Stats plugin update available!\nDownload it from Plugin Admin (if already available there) or GitHub.\nYour version: " + Constants.PluginVersion + "\nLatest: " + latest, "Code::Stats");
                        }
                    }
                    catch { }
                });


                if (string.IsNullOrEmpty(ApiKey))
                {
                    Stats = false;  // Disable stats reporting for this session/launch
                    PromptApiKey(); // Prompt for API token if not already set
                }

                // setup timer to process queued pulses
                pulseProcessor_tokensource             = new CancellationTokenSource();
                pulseProcessor_httpClientHandler       = new HttpClientHandler();
                pulseProcessor_httpClientHandler.Proxy = GetProxy();
                proxyChangePending    = false;
                pulseProcessor_client = new HttpClient(pulseProcessor_httpClientHandler);
                timer.Interval        = pulseFrequency;
                timer.Elapsed        += ProcessPulses;
                timer.Start();

                if (Stats)
                {
                    ReportStats();
                }

                Logger.Info(string.Format("Finished initializing Code::Stats v{0}", Constants.PluginVersion));
            }
            catch (Exception ex)
            {
                Logger.Error("Error Initializing Code::Stats", ex);
            }
        }
Пример #5
0
        private static Task ProcessPulses(CancellationTokenSource tokenSource)
        {
            return(Task.Run(async() =>
            {
                if (pulseQueue != null && ((currentPulse != null && !currentPulse.isEmpty()) || !pulseQueue.IsEmpty) && EnoughTimePassed(DateTime.Now))
                {
                    if (currentPulse != null && !currentPulse.isEmpty())
                    {
                        pulseQueue.Enqueue(currentPulse);
                        currentPulse = new Pulse();
                        currentCount = 0;
                    }

                    if (String.IsNullOrWhiteSpace(ApiKey))
                    {
                        Logger.Debug("No API token - cannot pulse!");
                        return;
                    }

                    if (proxyChangePending)
                    {
                        pulseProcessor_httpClientHandler = new HttpClientHandler();
                        pulseProcessor_httpClientHandler.Proxy = GetProxy();
                        pulseProcessor_client = new HttpClient(pulseProcessor_httpClientHandler);
                        proxyChangePending = false;
                    }
                    //var client = new WebClient { Proxy = CodeStatsPackage.GetProxy() };
                    var jsonSerializer = new JavaScriptSerializer();

                    string URL;
                    bool usesCustomEndpoint = false;
                    if (String.IsNullOrWhiteSpace(ApiUrl))
                    {
                        URL = Constants.ApiMyPulsesEndpoint;
                    }
                    else
                    {
                        URL = ApiUrl;
                        usesCustomEndpoint = true;
                    }

                    /*client.Headers["User-Agent"] = Constants.PluginUserAgent;
                     * client.Headers["Content-Type"] = "application/json";
                     * client.Headers["Accept"] = "* /*";
                     * client.Headers["X-API-Token"] = ApiKey;*/

                    Pulse result;
                    while (pulseQueue.TryDequeue(out result))
                    {
                        if (!result.isEmpty())
                        {
                            bool error = false;
                            HttpResponseMessage response = null;
                            // Try to pulse to API
                            try
                            {
                                string json;
                                var httpRequestMessage = new HttpRequestMessage
                                {
                                    Method = HttpMethod.Post,
                                    RequestUri = new Uri(URL),
                                    Headers =
                                    {
                                        { "User-Agent",  Constants.PluginUserAgent },
                                        { "Accept",      "*/*"                     },
                                        { "X-API-Token", ApiKey                    }
                                    },
                                    Content = new StringContent(json = jsonSerializer.Serialize(result), Encoding.UTF8, "application/json")
                                };

                                Logger.Debug("Pulsing " + json);
                                response = await pulseProcessor_client.SendAsync(httpRequestMessage, tokenSource.Token);
                                response.EnsureSuccessStatusCode();
                                string JsonResult = await response.Content.ReadAsStringAsync();
                                _lastPulse = DateTime.Now;
                                if (!JsonResult.Contains(@"""ok""") && !JsonResult.Contains(@"success"))
                                {
                                    error = true;
                                    Logger.Error(@"Error pulsing, response does not contain ""ok"" or ""success"": " + JsonResult);
                                }
                            }
                            catch (TaskCanceledException)
                            {
                                pulseQueue.Enqueue(result); // requeue current pulse
                                return;
                            }
                            catch (HttpRequestException ex)
                            {
                                error = true;
                                if (response != null && response.StatusCode != 0)
                                {
                                    if ((int)response.StatusCode == 403)
                                    {
                                        Logger.Error("Could not pulse (error 403). Please make sure you entered a valid API token in Code::Stats settings.", ex);
                                        if (!_hasAlreadyShownInvalidApiTokenMessage) // we want to inform user only once, and if they do not provide the token, let's not bomb him with error each time after they type something
                                        {
                                            _hasAlreadyShownInvalidApiTokenMessage = true;
                                            MessageBox.Show("Could not pulse. Please make sure you entered a valid API token in Code::Stats settings.\nAll recorded XP from this session will be lost if you do not provide the correct API token!", "Code::Stats – error 403", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                            PromptApiKey();
                                        }
                                    }
                                    else if ((int)response.StatusCode == 404 && usesCustomEndpoint)
                                    {
                                        Logger.Error("Could not pulse (error 404). The entered custom endpoint (" + URL + ") is invalid. ", ex);
                                        MessageBox.Show("Could not pulse. Invalid API endpoint URL. Please make sure you entered a valid API URL in Code::Stats settings or delete the value altogether to restore the default.\nAll recorded XP from this session will be lost if you do not provide the correct API URL path!", "Code::Stats – error 404", MessageBoxButtons.OK, MessageBoxIcon.Error);

                                        _settingsForm.FocusTxtAPIURL();
                                        _settingsForm.ShowAPIURLTooltip();
                                        SettingsPopup();
                                        _settingsForm.ShowAPIURLTooltip();
                                    }
                                    else
                                    {
                                        Logger.Error("Could not pulse - HTTP error " + (int)response.StatusCode + ". Server response: " + response.Content.ReadAsStringAsync().Result, ex);
                                    }
                                }
                                else
                                {
                                    // response==null - no http status code available
                                    Logger.Error("Could not pulse. Are you behind a proxy? Try setting a proxy in Code::Stats settings with format https://user:pass@host:port. Exception Traceback", ex);
                                }
                            }
                            catch (Exception ex)
                            {
                                error = true;
                                Logger.Error("Error pulsing. Exception Traceback", ex);
                            }

                            if (error)
                            {
                                pulseQueue.Enqueue(result); // Requeue, since we failed to pulse
                                return;
                            }
                        }

                        if (tokenSource.Token.IsCancellationRequested)
                        {
                            tokenSource.Token.ThrowIfCancellationRequested();
                        }
                    }
                }
            }, tokenSource.Token));
        }
Пример #6
0
        private static void InitializeAsync()
        {
            try
            {
                // Delete existing log file to save space
                Logger.Delete();
            }
            catch { }

            try
            {
                Logger.Info(string.Format("Initializing Code::Stats v{0}", Constants.PluginVersion));

                //Logger.Debug(Assembly.GetExecutingAssembly().GetManifestResourceNames().ToString());
                //Logger.Debug(Assembly.GetExecutingAssembly().GetName().Name);

                Assembly     _assembly;
                StreamReader _textStreamReader;
                Stream       _stream;
                string       extensionMappingJson;

                try
                {
                    var client = new WebClient {
                        Proxy = CodeStatsPackage.GetProxy()
                    };
                    client.Headers[HttpRequestHeader.UserAgent] = Constants.PluginUserAgent;

                    try
                    {
                        extensionMappingJson = client.DownloadString("https://raw.githubusercontent.com/p0358/notepadpp-CodeStats/master/CodeStats/Resources/extension_mapping.json");
                        if (!extensionMappingJson.Trim().StartsWith("{") || !extensionMappingJson.Trim().EndsWith("}"))
                        {
                            extensionMappingJson = string.Empty;
                        }
                    }
                    catch (Exception ex)
                    {
                        extensionMappingJson = string.Empty;
                        Logger.Error("Exception when trying to download latest extension mappings, using local ones instead", ex);
                    }
                }
                catch
                {
                    extensionMappingJson = string.Empty;
                }

                if (String.IsNullOrWhiteSpace(extensionMappingJson))
                {
                    // Load precompiled/included extension mapping
                    _assembly            = Assembly.GetExecutingAssembly();
                    _stream              = _assembly.GetManifestResourceStream("CodeStats.Resources.extension_mapping.json");
                    _textStreamReader    = new StreamReader(_stream);
                    extensionMappingJson = _textStreamReader.ReadToEnd();
                }

                Logger.Debug("Extension mapping JSON: " + extensionMappingJson);

                //var json = "{\"id\":\"13\", \"value\": true}";
                var serializer = new JavaScriptSerializer();
                //var table = serializer.Deserialize<dynamic>(json);
                //Dictionary<string, string> values = serializer.Deserialize<Dictionary<string, string>>(json);

                extensionMapping = serializer.Deserialize <Dictionary <string, string> >(extensionMappingJson);

                //Logger.Debug(values["id"]);
                //Logger.Debug(table["value"]);
            }
            catch (Exception ex)
            {
                Logger.Error("Error loading extension mappings!", ex);
            }

            try
            {
                // Settings Form
                _settingsForm              = new CodeStats.Forms.SettingsForm();
                _settingsForm.ConfigSaved += SettingsFormOnConfigSaved;

                // Load config file
                _CodeStatsConfigFile = new ConfigFile();
                GetSettings();

                try
                {
                    // Check for updates
                    string latest = Constants.LatestPluginVersion();
                    if (Constants.PluginVersion != latest && !String.IsNullOrWhiteSpace(latest))
                    {
                        MessageBox.Show("There is Code::Stats plugin update available!\nDownload it from Plugin Manager or GitHub.\nYour version: " + Constants.PluginVersion + "\nLatest: " + latest, "Code::Stats");
                    }
                }
                catch { }

                currentPulse = new Pulse();

                if (string.IsNullOrEmpty(ApiKey))
                {
                    Stats = false;  // Disable stats reporting for this session/launch
                    PromptApiKey(); // Prompt for API token if not already set
                }

                // setup timer to process queued pulses
                timer.Interval = pulseFrequency;
                timer.Elapsed += ProcessPulses;
                timer.Start();

                if (Stats)
                {
                    ReportStats();
                }

                Logger.Info(string.Format("Finished initializing Code::Stats v{0}", Constants.PluginVersion));
            }
            catch (Exception ex)
            {
                Logger.Error("Error Initializing Code::Stats", ex);
            }
        }
Пример #7
0
        private static void ProcessPulses()
        {
            if (pulseQueue != null && ((currentPulse != null && !currentPulse.isEmpty()) || !pulseQueue.IsEmpty) && EnoughTimePassed(DateTime.Now))
            {
                if (currentPulse != null && !currentPulse.isEmpty())
                {
                    pulseQueue.Enqueue(currentPulse);
                    currentPulse = new Pulse();
                    currentCount = 0;
                }

                if (String.IsNullOrWhiteSpace(ApiKey))
                {
                    Logger.Debug("No API token - cannot pulse!");
                    return;
                }

                var client = new WebClient {
                    Proxy = CodeStatsPackage.GetProxy()
                };
                var jsonSerializer = new JavaScriptSerializer();

                string URL;
                if (String.IsNullOrWhiteSpace(_CodeStatsConfigFile.ApiUrl))
                {
                    URL = Constants.ApiMyPulsesEndpoint;
                }
                else
                {
                    URL = _CodeStatsConfigFile.ApiUrl;
                }
                client.Headers[HttpRequestHeader.UserAgent]   = Constants.PluginUserAgent;
                client.Headers[HttpRequestHeader.ContentType] = "application/json";
                client.Headers[HttpRequestHeader.Accept]      = "*/*";
                client.Headers["X-API-Token"] = ApiKey;

                Pulse result;
                while (pulseQueue.TryDequeue(out result))
                {
                    if (!result.isEmpty())
                    {
                        bool error = false;
                        // Try to pulse to API
                        try
                        {
                            string json = jsonSerializer.Serialize(result);
                            Logger.Debug("Pulsing " + json);
                            string HtmlResult = client.UploadString(URL, json);
                            _lastPulse = DateTime.Now;
                            if (!HtmlResult.Contains(@"""ok""") && !HtmlResult.Contains(@"success"))
                            {
                                error = true;
                                Logger.Error(@"Error pulsing, response does not contain ""ok"" or ""success"": " + HtmlResult);
                            }
                        }
                        catch (WebException ex)
                        {
                            error = true;
                            if (ex.Status == WebExceptionStatus.ProtocolError)
                            {
                                var response = ex.Response as HttpWebResponse;
                                if (response != null && (int)response.StatusCode == 403)
                                {
                                    if (!_shownInvalidApiTokenMessage) // we want to inform user only once, and if he does not provide the token, let's not bomb him with error each time after he types something
                                    {
                                        MessageBox.Show("Could not pulse. Please make sure you entered a valid API token in Code::Stats settings.", "Code::Stats - error 403", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                        _shownInvalidApiTokenMessage = true;
                                    }
                                    Logger.Error("Could not pulse. Please make sure you entered a valid API token in Code::Stats settings.", ex);
                                }
                                else
                                {
                                    // response==null - no http status code available
                                    Logger.Error("Could not pulse. Are you behind a proxy? Try setting a proxy in Code::Stats settings with format https://user:pass@host:port. Exception Traceback", ex);
                                }
                            }
                            else
                            {
                                Logger.Error("Could not pulse. Are you behind a proxy? Try setting a proxy in Code::Stats settings with format https://user:pass@host:port. Exception Traceback", ex);
                            }
                        }
                        catch (Exception ex)
                        {
                            error = true;
                            Logger.Error("Error pulsing. Exception Traceback", ex);
                        }

                        if (error)
                        {
                            pulseQueue.Enqueue(result); // Requeue, since we failed to pulse
                            return;
                        }
                    }
                }
            }

            UpdateStatusbar();
        }
        private static void InitializeAsync()
        {
            if (System.Net.ServicePointManager.SecurityProtocol != 0)
            {
                // If the value is not set to 0 (SystemDefault), disable old protocols and make sure TLS 1.3, 1.2, 1.1 are enabled
                System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
                System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Tls;
                System.Net.ServicePointManager.SecurityProtocol |= (SecurityProtocolType)12288 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
            }

            try
            {
                // Delete existing log file to save space
                Logger.Delete();
            }
            catch { }

            Logger.Info($"Initializing Code::Stats v{Constants.PluginVersion}");

            try
            {
                currentPulse = new Pulse();
                Logger.Info("Initialing settings form...");
                // Settings Form
                _settingsForm = new CodeStats.Forms.SettingsForm();
                _settingsForm.OnSettingsSaved += SettingsFormOnConfigSaved;
                Logger.Info("Initialized settings form");                 // it takes 5 seconds to get here from Initializing Code::Stats message...

                // Load config file
                codeStatsSettings = CodeStatsSettingsProvider.GetSingleton();
                GetSettings(true);

                Logger.Debug("Loaded config");

                LoadExtensionMapping();


                if (String.IsNullOrEmpty(codeStatsSettings.ApiKey))
                {
                    PromptApiKey();                     // Prompt for API token if not already set
                }

                // setup timer to process queued pulses
                pulseProcessor_tokensource       = new CancellationTokenSource();
                pulseProcessor_httpClientHandler = new HttpClientHandler
                {
                    Proxy = GetProxy()
                };
                proxyChangePending    = false;
                pulseProcessor_client = new HttpClient(pulseProcessor_httpClientHandler);
                timer.Interval        = pulseFrequency;
                timer.Elapsed        += ProcessPulses;
                timer.Start();


                Logger.Info($"Finished initializing Code::Stats v{Constants.PluginVersion}");
            }
            catch (Exception ex)
            {
                Logger.Error("Error Initializing Code::Stats", ex);
            }
        }