chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json;
|
||||
using QuantConnect.Util;
|
||||
|
||||
namespace QuantConnect.Notifications
|
||||
{
|
||||
/// <summary>
|
||||
/// Local/desktop implementation of messaging system for Lean Engine.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(NotificationJsonConverter))]
|
||||
public abstract class Notification
|
||||
{
|
||||
/// <summary>
|
||||
/// Method for sending implementations of notification object types.
|
||||
/// </summary>
|
||||
/// <remarks>SMS, Email and Web are all handled by the QC Messaging Handler. To implement your own notification type implement it here.</remarks>
|
||||
public virtual void Send()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Web Notification Class
|
||||
/// </summary>
|
||||
public class NotificationWeb : Notification
|
||||
{
|
||||
/// <summary>
|
||||
/// Optional email headers
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public Dictionary<string, string> Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Send a notification message to this web address
|
||||
/// </summary>
|
||||
public string Address { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Object data to send.
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public object Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for sending a notification SMS to a specified phone number
|
||||
/// </summary>
|
||||
/// <param name="address">Address to send to</param>
|
||||
/// <param name="data">Data to send</param>
|
||||
/// <param name="headers">Optional headers to use</param>
|
||||
public NotificationWeb(string address, object data = null, Dictionary<string, string> headers = null)
|
||||
{
|
||||
Address = address;
|
||||
Data = data;
|
||||
Headers = headers;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sms Notification Class
|
||||
/// </summary>
|
||||
public class NotificationSms : Notification
|
||||
{
|
||||
/// <summary>
|
||||
/// Send a notification message to this phone number
|
||||
/// </summary>
|
||||
public string PhoneNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Message to send. Limited to 160 characters
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for sending a notification SMS to a specified phone number
|
||||
/// </summary>
|
||||
/// <param name="number"></param>
|
||||
/// <param name="message"></param>
|
||||
public NotificationSms(string number, string message)
|
||||
{
|
||||
PhoneNumber = number;
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Email notification data.
|
||||
/// </summary>
|
||||
public class NotificationEmail : Notification
|
||||
{
|
||||
/// <summary>
|
||||
/// Optional email headers
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public Dictionary<string, string> Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Send to address:
|
||||
/// </summary>
|
||||
public string Address { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Email subject
|
||||
/// </summary>
|
||||
public string Subject { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Message to send.
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Email Data
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor for sending an email notification
|
||||
/// </summary>
|
||||
/// <param name="address">Address to send to, if null will default to users email. Will throw <see cref="ArgumentException"/> if invalid
|
||||
/// <see cref="Validate.EmailAddress"/></param>
|
||||
/// <param name="subject">Subject of the email. Will set to <see cref="string.Empty"/> if null</param>
|
||||
/// <param name="message">Message body of the email. Will set to <see cref="string.Empty"/> if null</param>
|
||||
/// <param name="data">Data to attach to the email. Will set to <see cref="string.Empty"/> if null</param>
|
||||
/// <param name="headers">Optional email headers to use</param>
|
||||
public NotificationEmail(string address, string subject = "", string message = "", string data = "", Dictionary<string, string> headers = null)
|
||||
{
|
||||
if (!Validate.EmailAddress(address))
|
||||
{
|
||||
throw new ArgumentException(Messages.NotificationEmail.InvalidEmailAddress(address));
|
||||
}
|
||||
|
||||
Address = address;
|
||||
Data = data ?? string.Empty;
|
||||
Message = message ?? string.Empty;
|
||||
Subject = subject ?? string.Empty;
|
||||
Headers = headers;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Telegram notification data
|
||||
/// </summary>
|
||||
public class NotificationTelegram : Notification
|
||||
{
|
||||
/// <summary>
|
||||
/// Send a notification message to this user on Telegram
|
||||
/// Can be either a personal ID or Group ID.
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Message to send. Limited to 4096 characters
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Token to use
|
||||
/// </summary>
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Token { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for sending a telegram notification to a specific User ID
|
||||
/// or group ID. Note: The bot must have an open chat with the user or be
|
||||
/// added to the group for messages to deliver.
|
||||
/// </summary>
|
||||
/// <param name="id">User Id or Group Id to send the message too</param>
|
||||
/// <param name="message">Message to send</param>
|
||||
/// <param name="token">Bot token to use, if null defaults to "telegram-token"
|
||||
/// in config on send</param>
|
||||
public NotificationTelegram(string id, string message, string token = null)
|
||||
{
|
||||
Id = id;
|
||||
Message = message;
|
||||
Token = token;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FTP notification data
|
||||
/// </summary>
|
||||
public class NotificationFtp : Notification
|
||||
{
|
||||
private static readonly Regex HostnameProtocolRegex = new(@"^[s]?ftp\:\/\/", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
private const int DefaultPort = 21;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to use SFTP or FTP.
|
||||
/// </summary>
|
||||
[JsonProperty("secure")]
|
||||
public bool Secure { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The FTP server hostname.
|
||||
/// </summary>
|
||||
[JsonProperty("host")]
|
||||
public string Hostname { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The FTP server port.
|
||||
/// </summary>
|
||||
[JsonProperty("port")]
|
||||
public int Port { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The FTP server username.
|
||||
/// </summary>
|
||||
[JsonProperty("username")]
|
||||
public string Username { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The FTP server password.
|
||||
/// </summary>
|
||||
[JsonProperty("password", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Password { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The path to file on the FTP server.
|
||||
/// </summary>
|
||||
[JsonProperty("fileDestinationPath")]
|
||||
public string FilePath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The contents of the file to send.
|
||||
/// </summary>
|
||||
[JsonProperty("fileContent")]
|
||||
public string FileContent { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The private key to use for authentication (optional).
|
||||
/// </summary>
|
||||
[JsonProperty("privateKey", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string PrivateKey { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The passphrase for the private key (optional).
|
||||
/// </summary>
|
||||
[JsonProperty("passphrase", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string PrivateKeyPassphrase { get; }
|
||||
|
||||
private NotificationFtp(string hostname, string username, string filePath, byte[] fileContent, bool secure, int? port)
|
||||
{
|
||||
Hostname = NormalizeHostname(hostname);
|
||||
Port = port ?? DefaultPort;
|
||||
Username = username;
|
||||
FilePath = filePath;
|
||||
FileContent = Convert.ToBase64String(fileContent);
|
||||
Secure = secure;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for a notification to sent as a file to an FTP server using password authentication.
|
||||
/// </summary>
|
||||
/// <param name="hostname">FTP server hostname</param>
|
||||
/// <param name="username">The FTP server username</param>
|
||||
/// <param name="password">The FTP server password</param>
|
||||
/// <param name="filePath">The path to file on the FTP server</param>
|
||||
/// <param name="fileContent">The contents of the file</param>
|
||||
/// <param name="secure">Whether to use SFTP or FTP. Defaults to true</param>
|
||||
/// <param name="port">The FTP server port. Defaults to 21</param>
|
||||
public NotificationFtp(string hostname, string username, string password, string filePath, byte[] fileContent,
|
||||
bool secure = true, int? port = null)
|
||||
: this(hostname, username, filePath, fileContent, secure, port)
|
||||
{
|
||||
if (string.IsNullOrEmpty(password))
|
||||
{
|
||||
throw new ArgumentException(Messages.NotificationFtp.MissingPassword);
|
||||
}
|
||||
|
||||
Password = password;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for a notification to sent as a file to an FTP server over SFTP using SSH keys.
|
||||
/// </summary>
|
||||
/// <param name="hostname">FTP server hostname</param>
|
||||
/// <param name="username">The FTP server username</param>
|
||||
/// <param name="privateKey">The private SSH key to use for authentication</param>
|
||||
/// <param name="privateKeyPassphrase">The optional passphrase to decrypt the private key.
|
||||
/// This can be empty or null if the private key is not encrypted</param>
|
||||
/// <param name="filePath">The path to file on the FTP server</param>
|
||||
/// <param name="fileContent">The contents of the file</param>
|
||||
/// <param name="port">The FTP server port. Defaults to 21</param>
|
||||
public NotificationFtp(string hostname, string username, string privateKey, string privateKeyPassphrase,
|
||||
string filePath, byte[] fileContent, int? port = null)
|
||||
: this(hostname, username, filePath, fileContent, true, port)
|
||||
{
|
||||
if (string.IsNullOrEmpty(privateKey))
|
||||
{
|
||||
throw new ArgumentException(Messages.NotificationFtp.MissingSSHKey);
|
||||
}
|
||||
|
||||
PrivateKey = privateKey;
|
||||
PrivateKeyPassphrase = privateKeyPassphrase;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for a notification to sent as a file to an FTP server using password authentication.
|
||||
/// </summary>
|
||||
/// <param name="hostname">FTP server hostname</param>
|
||||
/// <param name="username">The FTP server username</param>
|
||||
/// <param name="password">The FTP server password</param>
|
||||
/// <param name="filePath">The path to file on the FTP server</param>
|
||||
/// <param name="fileContent">The contents of the file</param>
|
||||
/// <param name="secure">Whether to use SFTP or FTP. Defaults to true</param>
|
||||
/// <param name="port">The FTP server port. Defaults to 21</param>
|
||||
public NotificationFtp(string hostname, string username, string password, string filePath, string fileContent,
|
||||
bool secure = true, int? port = null)
|
||||
: this(hostname, username, password, filePath, Encoding.ASCII.GetBytes(fileContent), secure, port)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for a notification to sent as a file to an FTP server over SFTP using SSH keys.
|
||||
/// </summary>
|
||||
/// <param name="hostname">FTP server hostname</param>
|
||||
/// <param name="username">The FTP server username</param>
|
||||
/// <param name="privateKey">The private SSH key to use for authentication</param>
|
||||
/// <param name="privateKeyPassphrase">The optional passphrase to decrypt the private key.
|
||||
/// This can be empty or null if the private key is not encrypted</param>
|
||||
/// <param name="filePath">The path to file on the FTP server</param>
|
||||
/// <param name="fileContent">The contents of the file</param>
|
||||
/// <param name="port">The FTP server port. Defaults to 21</param>
|
||||
public NotificationFtp(string hostname, string username, string privateKey, string privateKeyPassphrase,
|
||||
string filePath, string fileContent, int? port = null)
|
||||
: this(hostname, username, privateKey, privateKeyPassphrase, filePath, Encoding.ASCII.GetBytes(fileContent), port)
|
||||
{
|
||||
}
|
||||
|
||||
private static string NormalizeHostname(string hostname)
|
||||
{
|
||||
// Remove trailing slashes
|
||||
hostname = hostname.Trim().TrimEnd('/');
|
||||
// Remove protocol if present
|
||||
return HostnameProtocolRegex.Replace(hostname, "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory method for Json deserialization: the file contents are already encoded
|
||||
/// </summary>
|
||||
internal static NotificationFtp FromEncodedData(string hostname, string username, string password, string filePath, string encodedFileContent,
|
||||
bool secure, int? port)
|
||||
{
|
||||
var notification = new NotificationFtp(hostname, username, password, filePath, Array.Empty<byte>(), secure, port);
|
||||
notification.FileContent = encodedFileContent;
|
||||
return notification;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory method for Json deserialization: the file contents are already encoded
|
||||
/// </summary>
|
||||
internal static NotificationFtp FromEncodedData(string hostname, string username, string privateKey, string privateKeyPassphrase,
|
||||
string filePath, string encodedFileContent, int? port)
|
||||
{
|
||||
var notification = new NotificationFtp(hostname, username, privateKey, privateKeyPassphrase, filePath, Array.Empty<byte>(), port);
|
||||
notification.FileContent = encodedFileContent;
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="Notification"/>
|
||||
/// </summary>
|
||||
public static class NotificationExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Check if the notification can be sent (implements the <see cref="Notification.Send"/> method)
|
||||
/// </summary>
|
||||
/// <param name="notification">The notification</param>
|
||||
/// <returns>Whether the notification can be sent</returns>
|
||||
public static bool CanSend(this Notification notification)
|
||||
{
|
||||
if (notification == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var type = notification.GetType();
|
||||
return type != typeof(NotificationEmail) &&
|
||||
type != typeof(NotificationWeb) &&
|
||||
type != typeof(NotificationSms) &&
|
||||
type != typeof(NotificationTelegram) &&
|
||||
type != typeof(NotificationFtp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace QuantConnect.Notifications
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a <see cref="JsonConverter"/> to be used when deserializing to the <see cref="Notification"/> class.
|
||||
/// </summary>
|
||||
public class NotificationJsonConverter : JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Use default implementation to write the json
|
||||
/// </summary>
|
||||
public override bool CanWrite => false;
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param><param name="value">The value.</param><param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
throw new NotImplementedException(Messages.NotificationJsonConverter.WriteNotImplemented);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param><param name="objectType">Type of the object.</param><param name="existingValue">The existing value of object being read.</param><param name="serializer">The calling serializer.</param>
|
||||
/// <returns>
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
var jObject = JObject.Load(reader);
|
||||
|
||||
JToken token;
|
||||
if (jObject.TryGetValue("PhoneNumber", StringComparison.InvariantCultureIgnoreCase, out token))
|
||||
{
|
||||
var message = jObject.GetValue("Message", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
return new NotificationSms(token.ToString(), message?.ToString());
|
||||
}
|
||||
else if (jObject.TryGetValue("Subject", StringComparison.InvariantCultureIgnoreCase, out token))
|
||||
{
|
||||
var data = jObject.GetValue("Data", StringComparison.InvariantCultureIgnoreCase);
|
||||
var message = jObject.GetValue("Message", StringComparison.InvariantCultureIgnoreCase);
|
||||
var address = jObject.GetValue("Address", StringComparison.InvariantCultureIgnoreCase);
|
||||
var headers= jObject.GetValue("Headers", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
return new NotificationEmail(address?.ToString(), token.ToString(), message?.ToString(), data?.ToString(), headers?.ToObject<Dictionary<string, string>>());
|
||||
}
|
||||
else if (jObject.TryGetValue("Address", StringComparison.InvariantCultureIgnoreCase, out token))
|
||||
{
|
||||
var headers = jObject.GetValue("Headers", StringComparison.InvariantCultureIgnoreCase);
|
||||
var data = jObject.GetValue("Data", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
return new NotificationWeb(token.ToString(), data?.ToString(), headers?.ToObject<Dictionary<string, string>>());
|
||||
}
|
||||
else if (jObject.TryGetValue("Id", StringComparison.InvariantCultureIgnoreCase, out token))
|
||||
{
|
||||
var message = jObject.GetValue("Message", StringComparison.InvariantCultureIgnoreCase);
|
||||
var botToken = jObject.GetValue("Token", StringComparison.InvariantCultureIgnoreCase);
|
||||
return new NotificationTelegram(token.ToString(), message?.ToString(), botToken?.ToString());
|
||||
}
|
||||
else if (jObject.TryGetValue("host", StringComparison.InvariantCultureIgnoreCase, out token))
|
||||
{
|
||||
// This is an FTP notification
|
||||
var hostname = token.ToString();
|
||||
var port = jObject.GetValue("port", StringComparison.InvariantCultureIgnoreCase)?.ToObject<int?>();
|
||||
var username = jObject.GetValue("username", StringComparison.InvariantCultureIgnoreCase)?.ToString();
|
||||
var filePath = jObject.GetValue("fileDestinationPath", StringComparison.InvariantCultureIgnoreCase)?.ToString();
|
||||
var fileContent = jObject.GetValue("fileContent", StringComparison.InvariantCultureIgnoreCase)?.ToString();
|
||||
|
||||
if (jObject.TryGetValue("password", StringComparison.InvariantCultureIgnoreCase, out var password))
|
||||
{
|
||||
var secure = jObject.GetValue("secure", StringComparison.InvariantCultureIgnoreCase)?.ToObject<bool>() ?? true;
|
||||
return NotificationFtp.FromEncodedData(hostname, username, password.ToString(), filePath, fileContent, secure, port);
|
||||
}
|
||||
|
||||
var privateKey = jObject.GetValue("privateKey", StringComparison.InvariantCultureIgnoreCase)?.ToString();
|
||||
var passphrase = jObject.GetValue("passphrase", StringComparison.InvariantCultureIgnoreCase)?.ToString();
|
||||
return NotificationFtp.FromEncodedData(hostname, username, privateKey, passphrase, filePath, fileContent, port);
|
||||
}
|
||||
|
||||
throw new NotImplementedException(Messages.NotificationJsonConverter.UnexpectedJsonObject(jObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance can convert the specified object type.
|
||||
/// </summary>
|
||||
/// <param name="objectType">Type of the object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(Notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using Python.Runtime;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace QuantConnect.Notifications
|
||||
{
|
||||
/// <summary>
|
||||
/// Local/desktop implementation of messaging system for Lean Engine.
|
||||
/// </summary>
|
||||
public class NotificationManager
|
||||
{
|
||||
private readonly bool _liveMode;
|
||||
|
||||
/// <summary>
|
||||
/// Public access to the messages
|
||||
/// </summary>
|
||||
public ConcurrentQueue<Notification> Messages { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the messaging system
|
||||
/// </summary>
|
||||
public NotificationManager(bool liveMode)
|
||||
{
|
||||
_liveMode = liveMode;
|
||||
Messages = new ConcurrentQueue<Notification>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send an email to the address specified for live trading notifications.
|
||||
/// </summary>
|
||||
/// <param name="subject">Subject of the email</param>
|
||||
/// <param name="message">Message body, up to 10kb</param>
|
||||
/// <param name="data">Data attachment (optional)</param>
|
||||
/// <param name="address">Email address to send to, if null will default to users email</param>
|
||||
/// <param name="headers">Optional email headers to use</param>
|
||||
public bool Email(string address, string subject, string message, string data, PyObject headers)
|
||||
{
|
||||
return Email(address, subject, message, data, headers.ConvertToDictionary<string, string>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send an email to the address specified for live trading notifications.
|
||||
/// </summary>
|
||||
/// <param name="subject">Subject of the email</param>
|
||||
/// <param name="message">Message body, up to 10kb</param>
|
||||
/// <param name="data">Data attachment (optional)</param>
|
||||
/// <param name="address">Email address to send to, if null will default to users email</param>
|
||||
/// <param name="headers">Optional email headers to use</param>
|
||||
public bool Email(string address, string subject, string message, string data = "", Dictionary<string, string> headers = null)
|
||||
{
|
||||
if (!_liveMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var email = new NotificationEmail(address, subject, message, data, headers);
|
||||
Messages.Enqueue(email);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send an SMS to the phone number specified
|
||||
/// </summary>
|
||||
/// <param name="phoneNumber">Phone number to send to</param>
|
||||
/// <param name="message">Message to send</param>
|
||||
public bool Sms(string phoneNumber, string message)
|
||||
{
|
||||
if (!_liveMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var sms = new NotificationSms(phoneNumber, message);
|
||||
Messages.Enqueue(sms);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Place REST POST call to the specified address with the specified DATA.
|
||||
/// Python overload for Headers parameter.
|
||||
/// </summary>
|
||||
/// <param name="address">Endpoint address</param>
|
||||
/// <param name="data">Data to send in body JSON encoded</param>
|
||||
/// <param name="headers">Optional headers to use</param>
|
||||
public bool Web(string address, object data, PyObject headers)
|
||||
{
|
||||
return Web(address, data, headers.ConvertToDictionary<string, string>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Place REST POST call to the specified address with the specified DATA.
|
||||
/// </summary>
|
||||
/// <param name="address">Endpoint address</param>
|
||||
/// <param name="data">Data to send in body JSON encoded (optional)</param>
|
||||
/// <param name="headers">Optional headers to use</param>
|
||||
public bool Web(string address, object data = null, Dictionary<string, string> headers = null)
|
||||
{
|
||||
if (!_liveMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var web = new NotificationWeb(address, data, headers);
|
||||
Messages.Enqueue(web);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a telegram message to the chat ID specified, supply token for custom bot.
|
||||
/// Note: Requires bot to have chat with user or be in the group specified by ID.
|
||||
/// </summary>
|
||||
/// <param name="id">Chat or group ID to send message to</param>
|
||||
/// <param name="message">Message to send</param>
|
||||
/// <param name="token">Bot token to use for this message</param>
|
||||
public bool Telegram(string id, string message, string token = null)
|
||||
{
|
||||
if (!_liveMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var telegram = new NotificationTelegram(id, message, token);
|
||||
Messages.Enqueue(telegram);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a file to the FTP specified server using password authentication over unsecure FTP.
|
||||
/// </summary>
|
||||
/// <param name="hostname">FTP server hostname</param>
|
||||
/// <param name="username">The FTP server username</param>
|
||||
/// <param name="password">The FTP server password</param>
|
||||
/// <param name="filePath">The path to file on the FTP server</param>
|
||||
/// <param name="fileContent">The contents of the file</param>
|
||||
/// <param name="port">The FTP server port. Defaults to 21</param>
|
||||
public bool Ftp(string hostname, string username, string password, string filePath, byte[] fileContent, int? port = null)
|
||||
{
|
||||
return Ftp(hostname, username, password, filePath, fileContent, secure: false, port);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a file to the FTP specified server using password authentication over unsecure FTP.
|
||||
/// </summary>
|
||||
/// <param name="hostname">FTP server hostname</param>
|
||||
/// <param name="username">The FTP server username</param>
|
||||
/// <param name="password">The FTP server password</param>
|
||||
/// <param name="filePath">The path to file on the FTP server</param>
|
||||
/// <param name="fileContent">The string contents of the file</param>
|
||||
/// <param name="port">The FTP server port. Defaults to 21</param>
|
||||
public bool Ftp(string hostname, string username, string password, string filePath, string fileContent, int? port = null)
|
||||
{
|
||||
return Ftp(hostname, username, password, filePath, fileContent, secure: false, port);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a file to the FTP specified server using password authentication over SFTP.
|
||||
/// </summary>
|
||||
/// <param name="hostname">FTP server hostname</param>
|
||||
/// <param name="username">The FTP server username</param>
|
||||
/// <param name="password">The FTP server password</param>
|
||||
/// <param name="filePath">The path to file on the FTP server</param>
|
||||
/// <param name="fileContent">The contents of the file</param>
|
||||
/// <param name="port">The FTP server port. Defaults to 21</param>
|
||||
public bool Sftp(string hostname, string username, string password, string filePath, byte[] fileContent, int? port = null)
|
||||
{
|
||||
return Ftp(hostname, username, password, filePath, fileContent, secure: true, port);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a file to the FTP specified server using password authentication over SFTP.
|
||||
/// </summary>
|
||||
/// <param name="hostname">FTP server hostname</param>
|
||||
/// <param name="username">The FTP server username</param>
|
||||
/// <param name="password">The FTP server password</param>
|
||||
/// <param name="filePath">The path to file on the FTP server</param>
|
||||
/// <param name="fileContent">The string contents of the file</param>
|
||||
/// <param name="port">The FTP server port. Defaults to 21</param>
|
||||
public bool Sftp(string hostname, string username, string password, string filePath, string fileContent, int? port = null)
|
||||
{
|
||||
return Ftp(hostname, username, password, filePath, fileContent, secure: true, port);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a file to the FTP specified server using password authentication over SFTP using SSH keys.
|
||||
/// </summary>
|
||||
/// <param name="hostname">FTP server hostname</param>
|
||||
/// <param name="username">The FTP server username</param>
|
||||
/// <param name="privateKey">The private SSH key to use for authentication</param>
|
||||
/// <param name="privateKeyPassphrase">The optional passphrase to decrypt the private key.
|
||||
/// This can be empty or null if the private key is not encrypted</param>
|
||||
/// <param name="filePath">The path to file on the FTP server</param>
|
||||
/// <param name="fileContent">The contents of the file</param>
|
||||
/// <param name="port">The FTP server port. Defaults to 21</param>
|
||||
public bool Sftp(string hostname, string username, string privateKey, string privateKeyPassphrase, string filePath, byte[] fileContent,
|
||||
int? port = null)
|
||||
{
|
||||
if (!_liveMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var ftp = new NotificationFtp(hostname, username, privateKey, privateKeyPassphrase, filePath, fileContent, port);
|
||||
Messages.Enqueue(ftp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a file to the FTP specified server using password authentication over SFTP using SSH keys.
|
||||
/// </summary>
|
||||
/// <param name="hostname">FTP server hostname</param>
|
||||
/// <param name="username">The FTP server username</param>
|
||||
/// <param name="privateKey">The private SSH key to use for authentication</param>
|
||||
/// <param name="privateKeyPassphrase">The optional passphrase to decrypt the private key.
|
||||
/// This can be empty or null if the private key is not encrypted</param>
|
||||
/// <param name="filePath">The path to file on the FTP server</param>
|
||||
/// <param name="fileContent">The string contents of the file</param>
|
||||
/// <param name="port">The FTP server port. Defaults to 21</param>
|
||||
public bool Sftp(string hostname, string username, string privateKey, string privateKeyPassphrase, string filePath, string fileContent,
|
||||
int? port = null)
|
||||
{
|
||||
if (!_liveMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var ftp = new NotificationFtp(hostname, username, privateKey, privateKeyPassphrase, filePath, fileContent, port);
|
||||
Messages.Enqueue(ftp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool Ftp(string hostname, string username, string password, string filePath, byte[] fileContent, bool secure = true, int? port = null)
|
||||
{
|
||||
if (!_liveMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var ftp = new NotificationFtp(hostname, username, password, filePath, fileContent, secure: secure, port);
|
||||
Messages.Enqueue(ftp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool Ftp(string hostname, string username, string password, string filePath, string fileContent, bool secure = true, int? port = null)
|
||||
{
|
||||
if (!_liveMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var ftp = new NotificationFtp(hostname, username, password, filePath, fileContent, secure: secure, port);
|
||||
Messages.Enqueue(ftp);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user