Merge branch 'markus' into kay.one

pull/7/merge
kay.one 13 years ago
commit c503b497ed

@ -81,6 +81,7 @@
<Compile Include="JobTests\BacklogSearchJobTest.cs" />
<Compile Include="JobTests\BannerDownloadJobTest.cs" />
<Compile Include="ProviderTests\ConfigFileProviderTest.cs" />
<Compile Include="ProviderTests\GrowlProviderTest.cs" />
<Compile Include="ProviderTests\DiskProviderTests\ExtractArchiveFixture.cs" />
<Compile Include="ProviderTests\PostDownloadProviderTests\PostDownloadProviderFixture.cs" />
<Compile Include="JobTests\SearchJobTest.cs" />

@ -0,0 +1,73 @@
using System;
using AutoMoq;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
// ReSharper disable InconsistentNaming
namespace NzbDrone.Core.Test.ProviderTests
{
[Explicit]
[TestFixture]
public class GrowlProviderTest : TestBase
{
[Test]
public void Register_should_add_new_application_to_local_growl_instance()
{
//Setup
var mocker = new AutoMoqer(MockBehavior.Strict);
//Act
mocker.Resolve<GrowlProvider>().Register("localhost", 23053, "");
//Assert
mocker.VerifyAllMocks();
}
[Test]
public void TestNotification_should_send_a_message_to_local_growl_instance()
{
//Setup
var mocker = new AutoMoqer(MockBehavior.Strict);
//Act
mocker.Resolve<GrowlProvider>().TestNotification("localhost", 23053, "");
//Assert
mocker.VerifyAllMocks();
}
[Test]
public void OnGrab_should_send_a_message_to_local_growl_instance()
{
//Setup
var mocker = new AutoMoqer(MockBehavior.Strict);
//Act
mocker.Resolve<GrowlProvider>().SendNotification("Episode Grabbed", "Series Title - 1x05 - Episode Title", "GRAB", "localhost", 23053, "");
//Assert
mocker.VerifyAllMocks();
}
[Test]
public void OnDownload_should_send_a_message_to_local_growl_instance()
{
//Setup
var mocker = new AutoMoqer(MockBehavior.Strict);
//Act
mocker.Resolve<GrowlProvider>().SendNotification("Episode Downloaded", "Series Title - 1x05 - Episode Title", "DOWNLOAD", "localhost", 23053, "");
//Assert
mocker.VerifyAllMocks();
}
}
}

@ -35,7 +35,6 @@ namespace NzbDrone.Core
}
}
public static void InitializeApp()
{
BindKernel();
@ -105,6 +104,9 @@ namespace NzbDrone.Core
private static void BindExternalNotifications()
{
_kernel.Bind<ExternalNotificationBase>().To<Xbmc>();
_kernel.Bind<ExternalNotificationBase>().To<Smtp>();
_kernel.Bind<ExternalNotificationBase>().To<Twitter>();
_kernel.Bind<ExternalNotificationBase>().To<Providers.ExternalNotification.Growl>();
var notifiers = _kernel.GetAll<ExternalNotificationBase>();
_kernel.Get<ExternalNotificationProvider>().InitializeNotifiers(notifiers.ToList());

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Model.Twitter
{
public class TwitterAuthorizationModel
{
public string Token { get; set; }
public string Url { get; set; }
}
}

@ -125,6 +125,12 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
</Reference>
<Reference Include="Growl.Connector">
<HintPath>..\packages\Growl.0.6\lib\Growl.Connector.dll</HintPath>
</Reference>
<Reference Include="Growl.CoreLibrary">
<HintPath>..\packages\Growl.0.6\lib\Growl.CoreLibrary.dll</HintPath>
</Reference>
<Reference Include="Ionic.Zip">
<HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
</Reference>
@ -145,6 +151,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MiniProfiler.1.9\lib\net40\MvcMiniProfiler.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.3.5.8\lib\35\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Ninject, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
<HintPath>..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll</HintPath>
</Reference>
@ -172,6 +181,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\TvdbLib.dll</HintPath>
</Reference>
<Reference Include="Twitterizer2">
<HintPath>..\packages\twitterizer.2.3.3\lib\35\Twitterizer2.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Constants.cs" />
@ -205,6 +217,7 @@
<Compile Include="Model\SabnzbdInfoModel.cs" />
<Compile Include="Model\Search\SearchModel.cs" />
<Compile Include="Model\Search\SearchType.cs" />
<Compile Include="Model\Twitter\TwitterAuthorizationModel.cs" />
<Compile Include="Model\UpdatePackage.cs" />
<Compile Include="Model\Xbmc\ActionType.cs" />
<Compile Include="Model\Xbmc\ActivePlayersResult.cs" />
@ -214,6 +227,10 @@
<Compile Include="Providers\Converting\HandbrakeProvider.cs" />
<Compile Include="Providers\Core\ConfigFileProvider.cs" />
<Compile Include="Providers\Core\UdpProvider.cs" />
<Compile Include="Providers\ExternalNotification\Growl.cs" />
<Compile Include="Providers\ExternalNotification\Twitter.cs" />
<Compile Include="Providers\ExternalNotification\Smtp.cs" />
<Compile Include="Providers\GrowlProvider.cs" />
<Compile Include="Providers\Jobs\BacklogSearchJob.cs" />
<Compile Include="Providers\Jobs\BannerDownloadJob.cs" />
<Compile Include="Providers\Jobs\ConvertEpisodeJob.cs" />
@ -225,6 +242,8 @@
<Compile Include="Providers\PostDownloadProvider.cs" />
<Compile Include="Providers\QualityTypeProvider.cs" />
<Compile Include="Providers\SearchProvider.cs" />
<Compile Include="Providers\SmtpProvider.cs" />
<Compile Include="Providers\TwitterProvider.cs" />
<Compile Include="Providers\UpdateProvider.cs" />
<Compile Include="Providers\Xbmc\ResourceManager.cs" />
<Compile Include="Model\Xbmc\TvShowResult.cs" />
@ -341,6 +360,10 @@
<Name>NzbDrone.Common</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="NzbDrone.ico" />
<Content Include="license.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@ -255,6 +255,115 @@ namespace NzbDrone.Core.Providers.Core
set { SetValue("UpdateUrl", value); }
}
public virtual Boolean SmtpNotifyOnGrab
{
get { return GetValueBoolean("SmtpNotifyOnGrab"); }
set { SetValue("SmtpNotifyOnGrab", value); }
}
public virtual Boolean SmtpNotifyOnDownload
{
get { return GetValueBoolean("SmtpNotifyOnDownload"); }
set { SetValue("SmtpNotifyOnDownload", value); }
}
public virtual string SmtpServer
{
get { return GetValue("SmtpServer", String.Empty); }
set { SetValue("SmtpServer", value); }
}
public virtual int SmtpPort
{
get { return GetValueInt("SmtpPort", 25); }
set { SetValue("SmtpPort", value); }
}
public virtual Boolean SmtpUseSsl
{
get { return GetValueBoolean("SmtpUseSsl"); }
set { SetValue("SmtpUseSsl", value); }
}
public virtual string SmtpUsername
{
get { return GetValue("SmtpUsername", String.Empty); }
set { SetValue("SmtpUsername", value); }
}
public virtual string SmtpPassword
{
get { return GetValue("SmtpPassword", String.Empty); }
set { SetValue("SmtpPassword", value); }
}
public virtual string SmtpFromAddress
{
get { return GetValue("SmtpFromAddress", String.Empty); }
set { SetValue("SmtpFromAddress", value); }
}
public virtual string SmtpToAddresses
{
get { return GetValue("SmtpToAddresses", String.Empty); }
set { SetValue("SmtpToAddresses", value); }
}
public virtual Boolean TwitterNotifyOnGrab
{
get { return GetValueBoolean("TwitterNotifyOnGrab"); }
set { SetValue("TwitterNotifyOnGrab", value); }
}
public virtual Boolean TwitterNotifyOnDownload
{
get { return GetValueBoolean("TwitterNotifyOnDownload"); }
set { SetValue("TwitterNotifyOnDownload", value); }
}
public virtual string TwitterAccessToken
{
get { return GetValue("TwitterAccessToken", String.Empty); }
set { SetValue("TwitterAccessToken", value); }
}
public virtual string TwitterAccessTokenSecret
{
get { return GetValue("TwitterAccessTokenSecret", String.Empty); }
set { SetValue("TwitterAccessTokenSecret", value); }
}
public virtual Boolean GrowlNotifyOnGrab
{
get { return GetValueBoolean("GrowlNotifyOnGrab"); }
set { SetValue("GrowlNotifyOnGrab", value); }
}
public virtual Boolean GrowlNotifyOnDownload
{
get { return GetValueBoolean("GrowlNotifyOnDownload"); }
set { SetValue("GrowlNotifyOnDownload", value); }
}
public virtual string GrowlHost
{
get { return GetValue("GrowlHost", String.Empty); }
set { SetValue("GrowlHost", value); }
}
public virtual string GrowlPassword
{
get { return GetValue("GrowlPassword", String.Empty); }
set { SetValue("GrowlPassword", value); }
}
private string GetValue(string key)
{
return GetValue(key, String.Empty);

@ -0,0 +1,78 @@
using System;
using NLog;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers.ExternalNotification
{
public class Growl : ExternalNotificationBase
{
private readonly GrowlProvider _growlProvider;
private readonly Logger Logger = LogManager.GetCurrentClassLogger();
public Growl(ConfigProvider configProvider, GrowlProvider growlProvider)
: base(configProvider)
{
_growlProvider = growlProvider;
}
public override string Name
{
get { return "Growl"; }
}
public override void OnGrab(string message)
{
try
{
if(_configProvider.GrowlNotifyOnGrab)
{
_logger.Trace("Sending Notification to Growl");
const string title = "Episode Grabbed";
var growlHost = _configProvider.GrowlHost.Split(':');
var host = growlHost[0];
var port = Convert.ToInt32(growlHost[1]);
_growlProvider.SendNotification(title, message, host, "GRAB", port, _configProvider.GrowlPassword);
}
}
catch (Exception ex)
{
Logger.WarnException(ex.Message, ex);
throw;
}
}
public override void OnDownload(string message, Series series)
{
try
{
if (_configProvider.GrowlNotifyOnDownload)
{
_logger.Trace("Sending Notification to Growl");
const string title = "Episode Downloaded";
var growlHost = _configProvider.GrowlHost.Split(':');
var host = growlHost[0];
var port = Convert.ToInt32(growlHost[1]);
_growlProvider.SendNotification(title, message, host, "DOWNLOAD", port, _configProvider.GrowlPassword);
}
}
catch (Exception ex)
{
Logger.WarnException(ex.Message, ex);
throw;
}
}
public override void OnRename(string message, Series series)
{
}
}
}

@ -0,0 +1,51 @@
using System;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers.ExternalNotification
{
public class Smtp: ExternalNotificationBase
{
private readonly SmtpProvider _smtpProvider;
public Smtp(ConfigProvider configProvider, SmtpProvider smtpProvider)
: base(configProvider)
{
_smtpProvider = smtpProvider;
}
public override string Name
{
get { return "SMTP"; }
}
public override void OnGrab(string message)
{
const string subject = "NzbDrone [TV] - Grabbed";
var body = String.Format("{0} sent to SABnzbd queue.", message);
if (_configProvider.SmtpNotifyOnGrab)
{
_logger.Trace("Sending SMTP Notification");
_smtpProvider.SendEmail(subject, body);
}
}
public override void OnDownload(string message, Series series)
{
const string subject = "NzbDrone [TV] - Downloaded";
var body = String.Format("{0} Downloaded and sorted.", message);
if (_configProvider.SmtpNotifyOnDownload)
{
_logger.Trace("Sending SMTP Notification");
_smtpProvider.SendEmail(subject, body);
}
}
public override void OnRename(string message, Series series)
{
}
}
}

@ -0,0 +1,44 @@
using System;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
namespace NzbDrone.Core.Providers.ExternalNotification
{
public class Twitter : ExternalNotificationBase
{
private readonly TwitterProvider _twitterProvider;
public Twitter(ConfigProvider configProvider, TwitterProvider twitterProvider)
: base(configProvider)
{
_twitterProvider = twitterProvider;
}
public override string Name
{
get { return "Twitter"; }
}
public override void OnGrab(string message)
{
if (_configProvider.TwitterNotifyOnGrab)
{
_logger.Trace("Sending Notification to Twitter (On Grab)");
_twitterProvider.SendTweet("Download Started: " + message);
}
}
public override void OnDownload(string message, Series series)
{
if (_configProvider.TwitterNotifyOnDownload)
{
_logger.Trace("Sending Notification to Twitter (On Grab)");
_twitterProvider.SendTweet("Downloaded Complete: " + message);
}
}
public override void OnRename(string message, Series series)
{
}
}
}

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Growl.Connector;
using NLog;
namespace NzbDrone.Core.Providers
{
public class GrowlProvider
{
private readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly Application _growlApplication = new Application("NzbDrone");
private GrowlConnector _growlConnector;
private List<NotificationType> _notificationTypes;
public GrowlProvider()
{
_notificationTypes = GetNotificationTypes();
_growlApplication.Icon = "https://github.com/NzbDrone/NzbDrone/raw/master/NzbDrone.Core/NzbDrone.jpg";
}
public virtual void Register(string hostname, int port, string password)
{
Logger.Trace("Registering NzbDrone with Growl host: {0}:{1}", hostname, port);
_growlConnector = new GrowlConnector(password, hostname, port);
_growlConnector.Register(_growlApplication, _notificationTypes.ToArray());
}
public virtual void TestNotification(string hostname, int port, string password)
{
const string title = "Test Notification";
const string message = "This is a test message from NzbDrone";
SendNotification(title, message, "TEST", hostname, port, password);
}
public virtual void SendNotification(string title, string message, string notificationTypeName, string hostname, int port, string password)
{
var notificationType = _notificationTypes.Single(n => n.Name == notificationTypeName);
var notification = new Notification("NzbDrone", notificationType.Name, DateTime.Now.Ticks.ToString(), title, message);
_growlConnector = new GrowlConnector(password, hostname, port);
Logger.Trace("Sending Notification to: {0}:{1}", hostname, port);
_growlConnector.Notify(notification);
}
private List<NotificationType> GetNotificationTypes()
{
var notificationTypes = new List<NotificationType>();
notificationTypes.Add(new NotificationType("TEST", "Test"));
notificationTypes.Add(new NotificationType("GRAB", "Episode Grabbed"));
notificationTypes.Add(new NotificationType("DOWNLOAD", "Episode Complete"));
return notificationTypes;
}
}
}

@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using NLog;
using Ninject;
using NzbDrone.Core.Providers.Core;
namespace NzbDrone.Core.Providers
{
public class SmtpProvider
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly ConfigProvider _configProvider;
[Inject]
public SmtpProvider(ConfigProvider configProvider)
{
_configProvider = configProvider;
}
public virtual bool SendEmail(string subject, string body, bool htmlBody = false)
{
//Create the Email message
var email = new MailMessage();
//Set the addresses
email.From = new MailAddress(_configProvider.SmtpFromAddress);
//Allow multiple to addresses (split on each comma)
foreach (var toAddress in _configProvider.SmtpToAddresses.Split(','))
{
email.To.Add(toAddress.Trim());
}
//Set the Subject
email.Subject = subject;
//Set the Body
email.Body = body;
//Html Body
email.IsBodyHtml = htmlBody;
//Handle credentials
var username = _configProvider.SmtpUsername;
var password = _configProvider.SmtpPassword;
NetworkCredential credentials = null;
if (!String.IsNullOrWhiteSpace(username))
credentials = new NetworkCredential(username, password);
//Send the email
return Send(email, _configProvider.SmtpServer, _configProvider.SmtpPort, _configProvider.SmtpUseSsl, credentials);
}
public virtual bool SendTestEmail(string server, int port, bool ssl, string username, string password, string fromAddress, string toAddresses)
{
var subject = "NzbDrone SMTP Test Notification";
var body = "This is a test email from NzbDrone, if you received this message you properly configured your SMTP settings! (Now save them!)";
//Create the Email message
var email = new MailMessage();
//Set the addresses
email.From = new MailAddress(fromAddress);
//Allow multiple to addresses (split on each comma)
foreach (var toAddress in toAddresses.Split(','))
{
email.To.Add(toAddress.Trim());
}
//Set the Subject
email.Subject = subject;
//Set the Body
email.Body = body;
//Html Body
email.IsBodyHtml = false;
//Handle credentials
NetworkCredential credentials = null;
if (!String.IsNullOrWhiteSpace(username))
credentials = new NetworkCredential(username, password);
//Send the email
return Send(email, _configProvider.SmtpServer, _configProvider.SmtpPort, _configProvider.SmtpUseSsl, credentials);
}
public virtual bool Send(MailMessage email, string server, int port, bool ssl, NetworkCredential credentials)
{
try
{
//Create the SMTP connection
var smtp = new SmtpClient(server, port);
//Enable SSL
smtp.EnableSsl = ssl;
//Credentials
smtp.Credentials = credentials;
//Send the email
smtp.Send(email);
return true;
}
catch (Exception ex)
{
Logger.Error("There was an error sending an email.");
Logger.TraceException(ex.Message, ex);
return false;
}
}
}
}

@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLog;
using Ninject;
using NzbDrone.Core.Model;
using NzbDrone.Core.Model.Twitter;
using NzbDrone.Core.Providers.Core;
using Twitterizer;
namespace NzbDrone.Core.Providers
{
public class TwitterProvider
{
private readonly ConfigProvider _configProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private const string ConsumerKey = "umKU6jBWpFbHTuqQbW2VlQ";
private const string ConsumerSecret = "e30OXkI6qrZWS35hbUUnrQQ8J2R9XNpccQNWAVK10";
[Inject]
public TwitterProvider(ConfigProvider configProvider)
{
_configProvider = configProvider;
}
public virtual TwitterAuthorizationModel GetAuthorization()
{
try
{
OAuthTokenResponse requestToken = OAuthUtility.GetRequestToken(ConsumerKey, ConsumerSecret, "oob", null);
Uri authorizationUri = OAuthUtility.BuildAuthorizationUri(requestToken.Token);
return new TwitterAuthorizationModel
{
Token = requestToken.Token,
Url = authorizationUri.ToString()
};
}
catch (Exception ex)
{
Logger.Warn("Failed to get Twitter authorization URL.");
Logger.TraceException(ex.Message, ex);
return null;
}
}
public virtual bool GetAndSaveAccessToken(string authToken, string verifier)
{
try
{
Logger.Debug("Attempting to get the AccessToken from Twitter");
OAuthTokenResponse accessToken = OAuthUtility.GetAccessToken(ConsumerKey, ConsumerSecret, authToken, verifier);
_configProvider.TwitterAccessToken = accessToken.Token;
_configProvider.TwitterAccessTokenSecret = accessToken.TokenSecret;
//Send a tweet to test!
SendTweet("I have just setup tweet notifications for NzbDrone!");
return true;
}
catch (Exception ex)
{
Logger.TraceException(ex.Message, ex);
return false;
}
}
public virtual bool SendTweet(string message)
{
try
{
Logger.Trace("Sending status update to twitter: {0}", message);
var accessToken = _configProvider.TwitterAccessToken;
var accessTokenSecret = _configProvider.TwitterAccessTokenSecret;
//If the access token or access token secret are not configured, log an error and return
if (String.IsNullOrWhiteSpace(accessToken) || String.IsNullOrWhiteSpace(accessTokenSecret))
{
Logger.Warn("Twitter Setup is incomplete, please check your settings");
return false;
}
var token = new OAuthTokens
{
AccessToken = accessToken,
AccessTokenSecret = accessTokenSecret,
ConsumerKey = ConsumerKey,
ConsumerSecret = ConsumerSecret
};
TwitterStatus.Update(token, message + " #NzbDrone");
return true;
}
catch (Exception ex)
{
Logger.DebugException(ex.Message, ex);
return false;
}
}
}
}

@ -37,7 +37,7 @@
public static System.Drawing.Bitmap GetIconAsImage(string Name)
{
System.IO.Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("{0}.Icons.{1}.ico", typeof(ResourceManager).Namespace, Name));
System.IO.Stream stm = typeof(ResourceManager).Assembly.GetManifestResourceStream(string.Format("NzbDrone.Core.{0}.ico", Name));
if (stm == null) return null;
System.Drawing.Bitmap bmp;
using (System.Drawing.Icon ico = new System.Drawing.Icon(stm))

@ -0,0 +1,25 @@
Growl.NET GNTP Connector Library
-----------------------------------------------
Copyright (c) 2008 - Growl for Windows
All rights reserved
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.

@ -1,8 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DotNetZip" version="1.9.1.8" />
<package id="Growl" version="0.6" />
<package id="MiniProfiler" version="1.9" />
<package id="Newtonsoft.Json" version="3.5.8" />
<package id="Ninject" version="2.2.1.4" />
<package id="NLog" version="2.0.0.2000" />
<package id="SqlServerCompact" version="4.0.8482.1" />
<package id="twitterizer" version="2.3.3" />
</packages>

@ -2,7 +2,9 @@
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using NLog;
using NzbDrone.Core.Model;
using NzbDrone.Core.Model.Twitter;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Jobs;
using NzbDrone.Web.Models;
@ -13,11 +15,18 @@ namespace NzbDrone.Web.Controllers
{
private readonly JobProvider _jobProvider;
private readonly SabProvider _sabProvider;
private readonly SmtpProvider _smtpProvider;
private readonly TwitterProvider _twitterProvider;
public CommandController(JobProvider jobProvider, SabProvider sabProvider)
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public CommandController(JobProvider jobProvider, SabProvider sabProvider,
SmtpProvider smtpProvider, TwitterProvider twitterProvider)
{
_jobProvider = jobProvider;
_sabProvider = sabProvider;
_smtpProvider = smtpProvider;
_twitterProvider = twitterProvider;
}
public JsonResult RssSync()
@ -58,9 +67,39 @@ namespace NzbDrone.Web.Controllers
catch (Exception ex)
{
//Todo: Log the error
throw;
Logger.Warn("Unable to get Categories from SABnzbd");
Logger.DebugException(ex.Message, ex);
return Json(new NotificationResult { Title = "Failed", Text = "Unable to get SABnzbd Categories", NotificationType = NotificationType.Error });
}
}
[HttpPost]
public JsonResult SendTestEmail(string server, int port, bool ssl, string username, string password, string fromAddress, string toAddresses)
{
if (_smtpProvider.SendTestEmail(server, port, ssl, username, password, fromAddress, toAddresses))
return Json(new NotificationResult { Title = "Successfully sent test email." });
return Json(new NotificationResult { Title = "Failed", Text = "Unable to send Email, please check your settings", NotificationType = NotificationType.Error });
}
public JsonResult GetTwitterAuthorization()
{
var result = _twitterProvider.GetAuthorization();
if (result == null)
return Json(new NotificationResult { Title = "Failed", Text = "Unable to get Twitter Authorization", NotificationType = NotificationType.Error }, JsonRequestBehavior.AllowGet);
return new JsonResult { Data = result, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
public JsonResult VerifyTwitterAuthorization(string token, string verifier)
{
var result = _twitterProvider.GetAndSaveAccessToken(token, verifier);
if (!result)
return Json(new NotificationResult { Title = "Failed", Text = "Unable to verify Twitter Authorization", NotificationType = NotificationType.Error }, JsonRequestBehavior.AllowGet);
return Json(new NotificationResult { Title = "Successfully verified Twitter Authorization." }, JsonRequestBehavior.AllowGet);
}
}
}

@ -160,7 +160,20 @@ namespace NzbDrone.Web.Controllers
XbmcCleanLibrary = _configProvider.XbmcCleanLibrary,
XbmcHosts = _configProvider.XbmcHosts,
XbmcUsername = _configProvider.XbmcUsername,
XbmcPassword = _configProvider.XbmcPassword
XbmcPassword = _configProvider.XbmcPassword,
SmtpEnabled = _externalNotificationProvider.GetSettings(typeof(Smtp)).Enable,
SmtpNotifyOnGrab = _configProvider.SmtpNotifyOnGrab,
SmtpNotifyOnDownload = _configProvider.SmtpNotifyOnGrab,
SmtpServer = _configProvider.SmtpServer,
SmtpPort = _configProvider.SmtpPort,
SmtpUseSsl = _configProvider.SmtpUseSsl,
SmtpUsername = _configProvider.SmtpUsername,
SmtpPassword = _configProvider.SmtpPassword,
SmtpFromAddress = _configProvider.SmtpFromAddress,
SmtpToAddresses = _configProvider.SmtpToAddresses,
TwitterEnabled = _externalNotificationProvider.GetSettings(typeof(Twitter)).Enable,
TwitterNotifyOnGrab = _configProvider.TwitterNotifyOnGrab,
TwitterNotifyOnDownload = _configProvider.TwitterNotifyOnDownload
};
return View(model);
@ -433,6 +446,29 @@ namespace NzbDrone.Web.Controllers
_configProvider.XbmcUsername = data.XbmcUsername;
_configProvider.XbmcPassword = data.XbmcPassword;
//SMTP
var smtpSettings = _externalNotificationProvider.GetSettings(typeof (Smtp));
smtpSettings.Enable = data.SmtpEnabled;
_externalNotificationProvider.SaveSettings(smtpSettings);
_configProvider.SmtpNotifyOnGrab = data.SmtpNotifyOnGrab;
_configProvider.SmtpNotifyOnDownload = data.SmtpNotifyOnDownload;
_configProvider.SmtpServer = data.SmtpServer;
_configProvider.SmtpPort = data.SmtpPort;
_configProvider.SmtpUseSsl = data.SmtpUseSsl;
_configProvider.SmtpUsername = data.SmtpUsername;
_configProvider.SmtpPassword = data.SmtpPassword;
_configProvider.SmtpFromAddress = data.SmtpFromAddress;
_configProvider.SmtpToAddresses = data.SmtpToAddresses;
//Twitter
var twitterSettings = _externalNotificationProvider.GetSettings(typeof(Twitter));
twitterSettings.Enable = data.TwitterEnabled;
_externalNotificationProvider.SaveSettings(twitterSettings);
_configProvider.TwitterNotifyOnGrab = data.TwitterNotifyOnGrab;
_configProvider.TwitterNotifyOnDownload = data.TwitterNotifyOnDownload;
return GetSuccessResult();
}

@ -5,6 +5,7 @@ namespace NzbDrone.Web.Models
{
public class NotificationSettingsModel
{
//XBMC
[DisplayName("Enabled")]
[Description("Enable notifications for XBMC?")]
public bool XbmcEnabled { get; set; }
@ -42,5 +43,72 @@ namespace NzbDrone.Web.Models
[Description("XBMC webserver password")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string XbmcPassword { get; set; }
//SMTP
[DisplayName("Enabled")]
[Description("Enable SMTP notifications?")]
public bool SmtpEnabled { get; set; }
[DisplayName("Notify on Grab")]
[Description("Send notification when episode is sent to SABnzbd?")]
public bool SmtpNotifyOnGrab { get; set; }
[DisplayName("Notify on Download")]
[Description("Send notification when episode is downloaded?")]
public bool SmtpNotifyOnDownload { get; set; }
[DataType(DataType.Text)]
[DisplayName("Server")]
[Description("SMTP Server Hostname")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string SmtpServer{ get; set; }
[DataType(DataType.Text)]
[DisplayName("Port")]
[Description("SMTP Server Port")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public int SmtpPort { get; set; }
[DisplayName("SSL")]
[Description("Does the SMTP Server use SSL?")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public bool SmtpUseSsl { get; set; }
[DataType(DataType.Text)]
[DisplayName("Username")]
[Description("SMTP Server authentication username")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string SmtpUsername { get; set; }
[DataType(DataType.Text)]
[DisplayName("Password")]
[Description("SMTP Server authentication password")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string SmtpPassword { get; set; }
[DataType(DataType.Text)]
[DisplayName("Send From Address")]
[Description("Sender Email address")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string SmtpFromAddress { get; set; }
[DataType(DataType.Text)]
[DisplayName("Send To Addresses")]
[Description("Comma separated list of addresses to email")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string SmtpToAddresses { get; set; }
//Twitter
[DisplayName("Enabled")]
[Description("Enable notifications for Twitter?")]
public bool TwitterEnabled { get; set; }
[DisplayName("Notify on Grab")]
[Description("Send notification when episode is sent to SABnzbd?")]
public bool TwitterNotifyOnGrab { get; set; }
[DisplayName("Notify on Download")]
[Description("Send notification when episode is downloaded?")]
public bool TwitterNotifyOnDownload { get; set; }
}
}

@ -930,6 +930,15 @@
<ItemGroup>
<Content Include="Views\Shared\LocalSearch.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Settings\Xbmc.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Settings\Smtp.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Settings\Twitter.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

@ -1,23 +1,8 @@
$(document).ready(function () {
var options = {
target: '#result',
//beforeSubmit: showRequest,
//success: showResponse,
type: 'post',
resetForm: false
};
$('#form').ajaxForm(options);
$('#save_button').removeAttr('disabled');
});
function showRequest(formData, jqForm, options) {
$("#result").empty().html('Saving...');
$("#form :input").attr("disabled", true);
$('#saveAjax').show();
}
function showResponse(responseText, statusText, xhr, $form) {
$("#result").empty().html(responseText);
$("#form :input").attr("disabled", false);
$('#saveAjax').hide();
}
});

@ -92,7 +92,7 @@
<button type="submit" id="save_button" disabled="disabled">Save</button>
}
</div>
<div id="result" class="hiddenResult"></div>
}
@section Scripts{
<script src="/Scripts/settingsForm.js" type="text/javascript"></script>

@ -23,13 +23,13 @@
@section MainContent{
<div id="stylized">
@using (Html.BeginForm("SaveIndexers", "Settings", FormMethod.Post, new { id = "form", name = "form", @class = "settingsForm" }))
{
<h1>Indexers</h1>
<p></p>
@using (Html.BeginForm("SaveIndexers", "Settings", FormMethod.Post, new { id = "form", name = "form", @class = "settingsForm" }))
{
<h1>Indexers</h1>
<p></p>
@Html.ValidationSummary(true, "Unable to save your settings. Please correct the errors and try again.")
<div>
@Html.ValidationSummary(true, "Unable to save your settings. Please correct the errors and try again.")
<div>
@{ Html.Telerik().PanelBar()
.Name("PanelBar")
//.HtmlAttributes(new { style = "width: 500px; margin: 10px;" })
@ -124,13 +124,11 @@
}).Render();
}
</div>
<br/>
<button type="submit" id="save_button" disabled="disabled">Save</button>
}
<br/>
<button type="submit" id="save_button" disabled="disabled">Save</button>
}
</div>
<div id="result" class="hiddenResult"></div>
}
@section Scripts{

@ -10,7 +10,7 @@
width: 560px;
border:solid 2px #CCCCCD;
padding: 5px;
margin-bottom: 10px;
margin-left: -8px;
}
.notifier h4
@ -29,6 +29,11 @@
border-bottom:solid 1px #CCCCCD;
padding-bottom:10px;
}
#save_button
{
margin-top: 10px;
}
</style>
}
@ -47,58 +52,34 @@
<h1>Notifications</h1>
<p></p>
<div id="xbmc" class="notifier clearfix">
<h4>XBMC</h4>
<div class="notifierLine"></div>
<label class="labelClass">@Html.LabelFor(m => m.XbmcEnabled)
<span class="small">@Html.DescriptionFor(m => m.XbmcEnabled)</span>
</label>
@Html.CheckBoxFor(m => m.XbmcEnabled, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcNotifyOnGrab)
<span class="small">@Html.DescriptionFor(m => m.XbmcNotifyOnGrab)</span>
</label>
@Html.CheckBoxFor(m => m.XbmcNotifyOnGrab, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcNotifyOnDownload)
<span class="small">@Html.DescriptionFor(m => m.XbmcNotifyOnDownload)</span>
</label>
@Html.CheckBoxFor(m => m.XbmcNotifyOnDownload, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcUpdateLibrary)
<span class="small">@Html.DescriptionFor(m => m.XbmcUpdateLibrary)</span>
</label>
@Html.CheckBoxFor(m => m.XbmcUpdateLibrary, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcCleanLibrary)
<span class="small">@Html.DescriptionFor(m => m.XbmcCleanLibrary)</span>
</label>
@Html.CheckBoxFor(m => m.XbmcCleanLibrary, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcHosts)
<span class="small">@Html.DescriptionFor(m => m.XbmcHosts)</span>
</label>
@Html.TextBoxFor(m => m.XbmcHosts, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcUsername)
<span class="small">@Html.DescriptionFor(m => m.XbmcUsername)</span>
</label>
@Html.TextBoxFor(m => m.XbmcUsername, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcPassword)
<span class="small">@Html.DescriptionFor(m => m.XbmcPassword)</span>
</label>
@Html.TextBoxFor(m => m.XbmcPassword, new { @class = "inputClass" })
<div id="tabs">
<ul>
<li><a href="#tabs-xbmc">XBMC</a></li>
<li><a href="#tabs-smtp">SMTP</a></li>
<li><a href="#tabs-twitter">Twitter</a></li>
</ul>
<div id="tabs-xbmc">
@{Html.RenderPartial("Xbmc", Model);}
</div>
<div id="tabs-smtp">
@{Html.RenderPartial("Smtp", Model);}
</div>
<div id="tabs-twitter">
@{Html.RenderPartial("Twitter", Model);}
</div>
</div>
<button type="submit" id="save_button" disabled="disabled">Save</button>
}
</div>
<div id="result" class="hiddenResult"></div>
}
@section Scripts{
<script src="/Scripts/settingsForm.js" type="text/javascript"></script>
<script>
$(function () {
$("#tabs").tabs();
});
</script>
}

@ -88,8 +88,6 @@ Settings
</div>
}
</div>
<div id="result" class="hiddenResult">
</div>
}
@section Scripts{
<script src="../../Scripts/Plugins/MicrosoftAjax.js" type="text/javascript"></script>

@ -0,0 +1,103 @@
@using NzbDrone.Web.Helpers
@model NzbDrone.Web.Models.NotificationSettingsModel
@{
Layout = null;
}
<div id="smtp" class="notifier clearfix">
<label class="labelClass">@Html.LabelFor(m => m.SmtpEnabled)
<span class="small">@Html.DescriptionFor(m => m.SmtpEnabled)</span>
</label>
@Html.CheckBoxFor(m => m.SmtpEnabled, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.SmtpNotifyOnGrab)
<span class="small">@Html.DescriptionFor(m => m.SmtpNotifyOnGrab)</span>
</label>
@Html.CheckBoxFor(m => m.SmtpNotifyOnGrab, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.SmtpNotifyOnDownload)
<span class="small">@Html.DescriptionFor(m => m.SmtpNotifyOnDownload)</span>
</label>
@Html.CheckBoxFor(m => m.SmtpNotifyOnDownload, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.SmtpServer)
<span class="small">@Html.DescriptionFor(m => m.SmtpServer)</span>
</label>
@Html.TextBoxFor(m => m.SmtpServer, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.SmtpPort)
<span class="small">@Html.DescriptionFor(m => m.SmtpPort)</span>
</label>
@Html.TextBoxFor(m => m.SmtpPort, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.SmtpUseSsl)
<span class="small">@Html.DescriptionFor(m => m.SmtpUseSsl)</span>
</label>
@Html.CheckBoxFor(m => m.SmtpUseSsl, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.SmtpUsername)
<span class="small">@Html.DescriptionFor(m => m.SmtpUsername)</span>
</label>
@Html.TextBoxFor(m => m.SmtpUsername, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.SmtpPassword)
<span class="small">@Html.DescriptionFor(m => m.SmtpPassword)</span>
</label>
@Html.TextBoxFor(m => m.SmtpPassword, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.SmtpFromAddress)
<span class="small">@Html.DescriptionFor(m => m.SmtpFromAddress)</span>
</label>
@Html.TextBoxFor(m => m.SmtpFromAddress, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.SmtpToAddresses)
<span class="small">@Html.DescriptionFor(m => m.SmtpToAddresses)</span>
</label>
@Html.TextBoxFor(m => m.SmtpToAddresses, new { @class = "inputClass" })
</div>
<input type="button" onclick="testSmtpSettings();" value="Test SMTP" id="smtpTest"/>
@*Move this somewhere better*@
<style>
#smtpTest
{
margin-top: 10px;
margin-bottom: 10px;
margin-left: 220px;
}
</style>
<script type="text/javascript">
function testSmtpSettings() {
//Get the variables
var server = $('#SmtpServer').val();
var port = $('#SmtpPort').val();
var ssl = $('#SmtpUseSsl').val();
var username = $('#SmtpUsername').val();
var password = $('#SmtpPassword').val();
var fromAddress = $('#SmtpFromAddress').val();
var toAddresses = $('#SmtpToAddresses').val();
//Send the data!
$.ajax({
type: "POST",
url: '../Command/SendTestEmail',
data: jQuery.param({
server: server,
port: port,
ssl: ssl,
username: username,
password: password,
fromAddress: fromAddress,
toAddresses: toAddresses
}),
error: function (req, status, error) {
alert("Sorry! We could send a test email at this time. " + error);
}
});
return false;
}
</script>

@ -40,7 +40,6 @@
<button type="submit" id="save_button" disabled="disabled">Save</button>
}
</div>
<div id="result" class="hiddenResult"></div>
}
@section Scripts{
<script src="/Scripts/settingsForm.js" type="text/javascript"></script>

@ -0,0 +1,76 @@
@using NzbDrone.Web.Helpers
@model NzbDrone.Web.Models.NotificationSettingsModel
@{
Layout = null;
}
<div id="twitter" class="notifier clearfix">
<label class="labelClass">@Html.LabelFor(m => m.TwitterEnabled)
<span class="small">@Html.DescriptionFor(m => m.TwitterEnabled)</span>
</label>
@Html.CheckBoxFor(m => m.TwitterEnabled, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.TwitterNotifyOnGrab)
<span class="small">@Html.DescriptionFor(m => m.TwitterNotifyOnGrab)</span>
</label>
@Html.CheckBoxFor(m => m.TwitterNotifyOnGrab, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.TwitterNotifyOnDownload)
<span class="small">@Html.DescriptionFor(m => m.TwitterNotifyOnDownload)</span>
</label>
@Html.CheckBoxFor(m => m.TwitterNotifyOnDownload, new { @class = "inputClass checkClass" })
<label class="labelClass">Request Authorization
<span class="small">Begin Twitter authorization for NzbDrone</span>
</label>
<input type="button" onclick="requestTwitterAuthorization();" value="Requestion Authorization" class="inputClass"/>
<label class="labelClass">Verification PIN
<span class="small">PIN from Twitter to provide authorization to NzbDrone</span>
</label>
@Html.TextBox("twitterVerification", "", new { @class = "inputClass" })
<label class="labelClass">Verify & Test Authorization
<span class="small">Verify & Test Twitter authorization for NzbDrone (Send a test tweet)</span>
</label>
<input type="button" onclick="verifyTwitterAuthorization();" value="Test Authorization" class="inputClass"/>
@Html.Hidden("authorizationRequestToken")
</div>
<script type="text/javascript">
getAuthorizationUrl = '../Command/GetTwitterAuthorization';
verifyAuthorizationUrl = '../Command/VerifyTwitterAuthorization';
function requestTwitterAuthorization() {
$.ajax({
type: "GET",
url: getAuthorizationUrl,
error: function(req, status, error) {
alert("Sorry! We could get Twitter Authorization at this time. " + error);
},
success: function(data, textStatus, jqXHR) {
if (data.IsMessage)
return false;
$('#authorizationRequestToken').val(data.Token);
window.open(data.Url);
}
});
}
function verifyTwitterAuthorization() {
var token = $('#authorizationRequestToken').val();
var verifier = $('#twitterVerification').val();
$.ajax({
type: "GET",
url: verifyAuthorizationUrl,
data: jQuery.param({ token: token, verifier: verifier }),
error: function(req, status, error) {
alert("Sorry! We could verify Twitter Authorization at this time. " + error);
}
});
}
</script>

@ -0,0 +1,48 @@
@using NzbDrone.Web.Helpers
@model NzbDrone.Web.Models.NotificationSettingsModel
@{
Layout = null;
}
<div id="xbmc" class="notifier clearfix">
<label class="labelClass">@Html.LabelFor(m => m.XbmcEnabled)
<span class="small">@Html.DescriptionFor(m => m.XbmcEnabled)</span>
</label>
@Html.CheckBoxFor(m => m.XbmcEnabled, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcNotifyOnGrab)
<span class="small">@Html.DescriptionFor(m => m.XbmcNotifyOnGrab)</span>
</label>
@Html.CheckBoxFor(m => m.XbmcNotifyOnGrab, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcNotifyOnDownload)
<span class="small">@Html.DescriptionFor(m => m.XbmcNotifyOnDownload)</span>
</label>
@Html.CheckBoxFor(m => m.XbmcNotifyOnDownload, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcUpdateLibrary)
<span class="small">@Html.DescriptionFor(m => m.XbmcUpdateLibrary)</span>
</label>
@Html.CheckBoxFor(m => m.XbmcUpdateLibrary, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcCleanLibrary)
<span class="small">@Html.DescriptionFor(m => m.XbmcCleanLibrary)</span>
</label>
@Html.CheckBoxFor(m => m.XbmcCleanLibrary, new { @class = "inputClass checkClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcHosts)
<span class="small">@Html.DescriptionFor(m => m.XbmcHosts)</span>
</label>
@Html.TextBoxFor(m => m.XbmcHosts, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcUsername)
<span class="small">@Html.DescriptionFor(m => m.XbmcUsername)</span>
</label>
@Html.TextBoxFor(m => m.XbmcUsername, new { @class = "inputClass" })
<label class="labelClass">@Html.LabelFor(m => m.XbmcPassword)
<span class="small">@Html.DescriptionFor(m => m.XbmcPassword)</span>
</label>
@Html.TextBoxFor(m => m.XbmcPassword, new { @class = "inputClass" })
</div>

@ -55,8 +55,8 @@
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

Binary file not shown.

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Growl.Connector;
using Growl.CoreLibrary;
namespace $rootnamespace$
{
class GrowlHelper
{
public static void simpleGrowl(string title, string message = "")
{
GrowlConnector simpleGrowl = new GrowlConnector();
Growl.Connector.Application thisApp = new Growl.Connector.Application(System.Windows.Forms.Application.ProductName);
NotificationType simpleGrowlType = new NotificationType("SIMPLEGROWL");
simpleGrowl.Register(thisApp, new NotificationType[] { simpleGrowlType });
Notification myGrowl = new Notification(System.Windows.Forms.Application.ProductName, "SIMPLEGROWL", title, title, message);
simpleGrowl.Notify(myGrowl);
}
}
}

@ -0,0 +1,25 @@
Growl.NET GNTP Connector Library
-----------------------------------------------
Copyright (c) 2008 - Growl for Windows
All rights reserved
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,19 @@
Copyright (c) 2010, Patrick "Ricky" Smith
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
- Neither the name Twitterizer nor the names of its contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Loading…
Cancel
Save