diff --git a/src/NzbDrone.Api/Config/HostConfigResource.cs b/src/NzbDrone.Api/Config/HostConfigResource.cs index cc52c01c4..f8dde71a7 100644 --- a/src/NzbDrone.Api/Config/HostConfigResource.cs +++ b/src/NzbDrone.Api/Config/HostConfigResource.cs @@ -10,7 +10,8 @@ public class HostConfigResource : RestResource public Int32 SslPort { get; set; } public Boolean EnableSsl { get; set; } public Boolean LaunchBrowser { get; set; } - public Boolean AuthenticationEnabled { get; set; } + public bool AuthenticationEnabled { get; set; } + public Boolean AnalyticsEnabled { get; set; } public String Username { get; set; } public String Password { get; set; } public String LogLevel { get; set; } diff --git a/src/NzbDrone.Api/Frontend/Mappers/IndexHtmlMapper.cs b/src/NzbDrone.Api/Frontend/Mappers/IndexHtmlMapper.cs index e59fd0e44..a8172845a 100644 --- a/src/NzbDrone.Api/Frontend/Mappers/IndexHtmlMapper.cs +++ b/src/NzbDrone.Api/Frontend/Mappers/IndexHtmlMapper.cs @@ -6,6 +6,7 @@ using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Core.Analytics; using NzbDrone.Core.Configuration; namespace NzbDrone.Api.Frontend.Mappers @@ -13,6 +14,8 @@ namespace NzbDrone.Api.Frontend.Mappers public class IndexHtmlMapper : StaticResourceMapperBase { private readonly IDiskProvider _diskProvider; + private readonly IConfigFileProvider _configFileProvider; + private readonly IAnalyticsService _analyticsService; private readonly Func _cacheBreakProviderFactory; private readonly string _indexPath; private static readonly Regex ReplaceRegex = new Regex("(?<=(?:href|src|data-main)=\").*?(?=\")", RegexOptions.Compiled | RegexOptions.IgnoreCase); @@ -25,11 +28,14 @@ private string _generatedContent public IndexHtmlMapper(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, IConfigFileProvider configFileProvider, + IAnalyticsService analyticsService, Func cacheBreakProviderFactory, Logger logger) : base(diskProvider, logger) { _diskProvider = diskProvider; + _configFileProvider = configFileProvider; + _analyticsService = analyticsService; _cacheBreakProviderFactory = cacheBreakProviderFactory; _indexPath = Path.Combine(appFolderInfo.StartUpFolder, "UI", "index.html"); @@ -88,6 +94,8 @@ private string GetIndexText() text = text.Replace("API_KEY", API_KEY); text = text.Replace("APP_VERSION", BuildInfo.Version.ToString()); + text = text.Replace("APP_ANALYTICS", _analyticsService.IsEnabled.ToString().ToLowerInvariant()); + _generatedContent = text; return _generatedContent; diff --git a/src/NzbDrone.Core/Analytics/AnalyticsService.cs b/src/NzbDrone.Core/Analytics/AnalyticsService.cs new file mode 100644 index 000000000..8901817a9 --- /dev/null +++ b/src/NzbDrone.Core/Analytics/AnalyticsService.cs @@ -0,0 +1,28 @@ +using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Core.Configuration; + +namespace NzbDrone.Core.Analytics +{ + public interface IAnalyticsService + { + bool IsEnabled { get; } + } + + public class AnalyticsService : IAnalyticsService + { + private readonly IConfigFileProvider _configFileProvider; + + public AnalyticsService(IConfigFileProvider configFileProvider) + { + _configFileProvider = configFileProvider; + } + + public bool IsEnabled + { + get + { + return _configFileProvider.AnalyticsEnabled && RuntimeInfoBase.IsProduction; + } + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs b/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs index ecb23d0a2..1240529f8 100644 --- a/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs +++ b/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs @@ -27,6 +27,7 @@ public interface IConfigFileProvider : IHandleAsync, bool EnableSsl { get; } bool LaunchBrowser { get; } bool AuthenticationEnabled { get; } + bool AnalyticsEnabled { get; } string Username { get; } string Password { get; } string LogLevel { get; } @@ -139,6 +140,14 @@ public bool AuthenticationEnabled get { return GetValueBoolean("AuthenticationEnabled", false); } } + public bool AnalyticsEnabled + { + get + { + return GetValueBoolean("AnalyticsEnabled", true, persist: false); + } + } + public string Branch { get { return GetValue("Branch", "master").ToLowerInvariant(); } diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 8f1976560..15239f89c 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -109,6 +109,7 @@ Properties\SharedAssemblyInfo.cs + diff --git a/src/UI/Settings/General/GeneralViewTemplate.hbs b/src/UI/Settings/General/GeneralViewTemplate.hbs index 60e42c462..2028508bd 100644 --- a/src/UI/Settings/General/GeneralViewTemplate.hbs +++ b/src/UI/Settings/General/GeneralViewTemplate.hbs @@ -173,9 +173,33 @@ +
+ Analytics + +
+ + +
+
+
+
+
- Updating + Updates
diff --git a/src/UI/Shared/NzbDroneController.js b/src/UI/Shared/NzbDroneController.js index c08e14bea..c4584e3c7 100644 --- a/src/UI/Shared/NzbDroneController.js +++ b/src/UI/Shared/NzbDroneController.js @@ -25,6 +25,19 @@ define( else { document.title = title + ' - nzbdrone'; } + + if(window.NzbDrone.Analytics && window.Piwik){ + try { + var piwik = window.Piwik.getTracker('http://piwik.nzbdrone.com/piwik.php', 1); + piwik.setReferrerUrl(''); + piwik.setCustomUrl('http://local' + window.location.pathname); + piwik.setCustomVariable(1, 'version', window.NzbDrone.version, 'page'); + piwik.trackPageView(title); + } + catch (e){ + console.error(e); + } + } }, _onServerUpdated: function () { diff --git a/src/UI/index.html b/src/UI/index.html index 9477f7adf..3f2f5a199 100644 --- a/src/UI/index.html +++ b/src/UI/index.html @@ -75,10 +75,12 @@ window.NzbDrone = { ApiRoot: 'API_ROOT', ApiKey : 'API_KEY', - Version: 'APP_VERSION' + Version: 'APP_VERSION', + Analytics: APP_ANALYTICS }; + diff --git a/src/UI/piwik.js b/src/UI/piwik.js new file mode 100644 index 000000000..782ef13c4 --- /dev/null +++ b/src/UI/piwik.js @@ -0,0 +1,11 @@ +'use strict'; +if(window.NzbDrone.Analytics) { + var d = document; + var g = d.createElement('script'); + var s = d.getElementsByTagName('script')[0]; + g.type = 'text/javascript'; + g.async = true; + g.defer = true; + g.src = 'http://piwik.nzbdrone.com/piwik.js'; + s.parentNode.insertBefore(g, s); +} \ No newline at end of file