Twitch Integrations - Getting chatter's roles and name with capital letters - c#

I have a class created through a few different sources to connect, stay connected, read, and interact with a selected Twitch channel, but there seems to be no information as to how to do certain things.
One of the issues is that the names of the chatters are always in all lowercase characters.
The other issue is that there doesnt seem to be any information of users. Ie are they a mod, subscriber, VIP?
While the roles parts arent that high priority for me, I want for the names to be properly capitalized.
Is there any trick that can do this?
using System;
using System.IO;
using System.Net.Sockets;
using UnityEngine;
public class TwitchConnect : MonoBehaviour
{
public static TwitchConnect instance;
public TwitchAccountData TwitchSettings = new();
public event Action<string, string> OnChatMessage;
public event Action<string> OnLoggedIn;
public event Action OnLoggedOut;
public event Action<string> OnInvalidLogin;
public bool loggedIn = false;
private TcpClient Twitch;
private StreamReader Reader;
private StreamWriter Writer;
//private const string URL = "irc.chat.twitch.tv";
private const string URL = "irc.twitch.tv";
private const int PORT = 6667;
private float PingCounter = 0;
private string saveTwitchPath = "twitchauth.json";
private void Awake()
{
DontDestroyOnLoad(gameObject);
instance = this;
saveTwitchPath = Application.persistentDataPath + "/twitchauth.json";
LoadAccount();
}
public void UpdateAccount(string nUser, string nOAuth, string nChannel)
{
TwitchSettings.User = nUser;
TwitchSettings.OAuth = nOAuth;
TwitchSettings.Channel = nChannel;
}
public void ConnectToTwitch()
{
DisconnectFromTwitch();
Twitch = new TcpClient(URL, PORT);
Reader = new StreamReader(Twitch.GetStream());
Writer = new StreamWriter(Twitch.GetStream());
TwitchSettings.User = TwitchSettings.User.ToLower();
TwitchSettings.Channel = TwitchSettings.Channel.ToLower();
Writer.WriteLine("PASS " + TwitchSettings.OAuth);
Writer.WriteLine("NICK " + TwitchSettings.User);
Writer.WriteLine($"USER {TwitchSettings.User} 8 * :{TwitchSettings.User}");
Writer.WriteLine("JOIN #" + TwitchSettings.Channel);
Writer.Flush();//initiate connection
}
public void DisconnectFromTwitch()
{
loggedIn = false;
PingCounter = 0;
Twitch?.Dispose();
Reader?.Dispose();
Writer?.Dispose();
Twitch = null;
Reader = null;
Writer = null;
OnLoggedOut?.Invoke();
}
public void SaveAccount()
{
string jsonTwitch = JsonUtility.ToJson(TwitchSettings, true);
File.WriteAllText(saveTwitchPath, jsonTwitch, System.Text.Encoding.Unicode);
Debug.LogWarning("Twitch account settings saved!");
}
public void LoadAccount()
{
//twitch saved account settings - user, oauth, channel
if (File.Exists(saveTwitchPath))
{
string jsonSettings = File.ReadAllText(saveTwitchPath, System.Text.Encoding.Unicode);
JsonUtility.FromJsonOverwrite(jsonSettings, TwitchSettings);
Debug.LogWarning("Twitch account loaded, logging in...");
ConnectToTwitch();
}
}
public void SendIrcMessage(string message)
{
Writer.WriteLine(message);
Writer.Flush();
}
public void SendChatMessage(string message)
{
Writer.WriteLine($":{TwitchSettings.User}!{TwitchSettings.User}#{TwitchSettings.User}.tmi.twitch.tv PRIVMSG #{TwitchSettings.Channel} :{message}");
Writer.Flush();
}
private void Update()
{
if (Twitch == null) return;
if (!Twitch.Connected && loggedIn)
{
ConnectToTwitch();
}
PingCounter += Time.deltaTime;
if (PingCounter > 50)
{
Writer.WriteLine("PING " + URL);
Writer.Flush();
PingCounter = 0;
}
if (Twitch.Available > 0)
{
string message = Reader.ReadLine();
#if UNITY_EDITOR
Debug.Log(message);//DEBUG
#endif
if (message.Contains("PRIVMSG"))
{
int splitPoint = message.IndexOf("!");
string chatter = message[1..splitPoint];//get chatter name
splitPoint = message.IndexOf(":", 1);
string msg = message[(splitPoint + 1)..];//get message only
OnChatMessage?.Invoke(chatter, msg);
}
else if (message.Contains(":Welcome, GLHF!"))//successful login
{
SaveAccount();
loggedIn = true;
OnLoggedIn?.Invoke(TwitchSettings.User);
}
else if (message.Contains(":Invalid NICK"))
{
OnInvalidLogin?.Invoke("Invalid NICK");
}
else if (message.Contains(":Improperly formatted auth"))
{
OnInvalidLogin?.Invoke("Improperly formatted auth");
}
}
}
private void OnDestroy()
{
DisconnectFromTwitch();
}
}

For TMI - Twitch Messaging Interface to get DisplayName and Role information you need to enable some IRCv3 capabilities then updates your parser to extract the data.
Before PASS you should send
CAP REQ :twitch.tv/commands twitch.tv/tags
So,
Writer.WriteLine("PASS " + TwitchSettings.OAuth);
becomes
Writer.WriteLine("CAP REQ :twitch.tv/commands twitch.tv/tags");
Writer.WriteLine("PASS " + TwitchSettings.OAuth);
To enable additional data - https://dev.twitch.tv/docs/irc/capabilities
This will then add additioanl data to PRIVMSGs sent by Twitch.
These are commonly referered to as IRCv3 Tags.
This is an example from the documentations
#badge-info=;badges=broadcaster/1;client-nonce=28e05b1c83f1e916ca1710c44b014515;color=#0000FF;display-name=foofoo;emotes=62835:0-10;first-msg=0;flags=;id=f80a19d6-e35a-4273-82d0-cd87f614e767;mod=0;room-id=713936733;subscriber=0;tmi-sent-ts=1642696567751;turbo=0;user-id=713936733;user-type= :foofoo!foofoo#foofoo.tmi.twitch.tv PRIVMSG #bar :bleedPurple
https://dev.twitch.tv/docs/irc/send-receive-messages#receiving-chat-messages
This user:
sent the message bleedpurple in the channel bar
has the display-name of foofoo this will be the Capitislation of the user if any is set by the user
has the badges of broadcaster (version 1 of said badge)
So for VIP or moderator you would monitor for the badges of vip or moderator and so on for whatever roles you are looking for.
Further reading is on https://dev.twitch.tv/docs/irc/tags#privmsg-tags
Some badge examples:
Comma-separated list of chat badges in the form, <badge>/<version>. For example, admin/1. There are many possible badge values, but here are few:
admin
bits
broadcaster
moderator
subscriber
staff
turbo
You would normally poke the badges API (channel or global) for available badges nad versions of those badges.
But the salient role based badges are in this non exhuastive list.

Related

how to save firebase auth between scenes

Hello people im new with Unity and C#.
I have this script to create/login users and post in firebase database (with email and password).
I copied it from a youtube tutorial with a little few modifications
using System.Collections;
using System.Collections.Generic;
using FullSerializer;
using Proyecto26;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using Firebase.Auth;
public class PlayerScores : MonoBehaviour
{
public Text scoreText;
public InputField getScoreText;
public InputField emailText;
public InputField usernameText;
public InputField passwordText;
private System.Random random = new System.Random();
User user = new User();
private string databaseURL = "testingurl";
private string AuthKey = "testingapikey";
public static fsSerializer serializer = new fsSerializer();
public static int playerScore;
public static string playerName;
private string idToken;
public static string localId;
private string getLocalId;
private void Start()
{
playerScore = random.Next(0, 101);
scoreText.text = "Score: " + playerScore;
}
public void OnSubmit()
{
PostToDatabase();
Debug.Log("datos subidos a database");
}
public void OnGetScore()
{
GetLocalId();
}
private void UpdateScore()
{
scoreText.text = "Score: " + user.userScore;
}
private void PostToDatabase(bool emptyScore = false, string idTokenTemp = "")
{
if (idTokenTemp == "")
{
idTokenTemp = idToken;
}
User user = new User();
if (emptyScore)
{
user.userScore = 0;
}
RestClient.Put(databaseURL + "/" + localId + ".json?auth=" + idTokenTemp, user);
}
private void RetrieveFromDatabase()
{
RestClient.Get<User>(databaseURL + "/" + getLocalId + ".json?auth=" + idToken).Then(response =>
{
user = response;
UpdateScore();
});
}
public void SignUpUserButton()
{
SignUpUser(emailText.text, usernameText.text, passwordText.text);
}
public void SignInUserButton()
{
SignInUser(emailText.text, passwordText.text);
}
private void SignUpUser(string email, string username, string password)
{
string userData = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\",\"returnSecureToken\":true}";
RestClient.Post<SignResponse>("https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=" + AuthKey, userData).Then(
response =>
{
string emailVerification = "{\"requestType\":\"VERIFY_EMAIL\",\"idToken\":\"" + response.idToken + "\"}";
RestClient.Post(
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/getOobConfirmationCode?key=" + AuthKey,
emailVerification);
localId = response.localId;
playerName = username;
PostToDatabase(true, response.idToken);
Debug.Log("SingUp Correcto");
}).Catch(error =>
{
Debug.Log("falta email/password");
Debug.Log(error);
});
}
private void SignInUser(string email, string password)
{
string userData = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\",\"returnSecureToken\":true}";
RestClient.Post<SignResponse>("https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=" + AuthKey, userData).Then(
response =>
{
string emailVerification = "{\"idToken\":\"" + response.idToken + "\"}";
RestClient.Post(
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?key=" + AuthKey,
emailVerification).Then(
emailResponse =>
{
fsData emailVerificationData = fsJsonParser.Parse(emailResponse.Text);
EmailConfirmationInfo emailConfirmationInfo = new EmailConfirmationInfo();
serializer.TryDeserialize(emailVerificationData, ref emailConfirmationInfo).AssertSuccessWithoutWarnings();
if (emailConfirmationInfo.users[0].emailVerified)
{
idToken = response.idToken;
localId = response.localId;
GetUsername();
Debug.Log("Login Correcto");
SceneManager.LoadScene("SignInEdit"); //para logear correctamente solo necesita que el email y password sean correctos, el username no importa.
}
else
{
Debug.Log("You are stupid, you need to verify your email dumb");
}
});
}).Catch(error =>
{
Debug.Log(error);
});
}
private void GetUsername()
{
RestClient.Get<User>(databaseURL + "/" + localId + ".json?auth=" + idToken).Then(response =>
{
playerName = response.userName;
});
}
private void GetLocalId()
{
RestClient.Get(databaseURL + ".json?auth=" + idToken).Then(response =>
{
var username = getScoreText.text;
fsData userData = fsJsonParser.Parse(response.Text);
Dictionary<string, User> users = null;
serializer.TryDeserialize(userData, ref users);
foreach (var user in users.Values)
{
if (user.userName == username)
{
getLocalId = user.localId;
RetrieveFromDatabase();
break;
}
}
}).Catch(error =>
{
Debug.Log(error);
});
}
}
my problem is I cant save my firebase login between scenes, When I change scene I cant interact anymore with my firebase database.
I tried make a dontdestroyonload script and add a unity gameobject what is containing my PlayerScore script, but dont worked.
I readed im need to store my userid in a static variable to call it from anywhere but I dont know how because im prettly new with c# coding
Can someone give some guidance?, thanks.
PS: the script of above need another 3 script to works, where store/get some values.
If is necessary I add them.
I think that there might be some confusion here as I see a reference to the official Firebase Unity SDK mixed with raw REST calls in RestClient. I'll answer this assuming that you're ok with using the Unity SDK. This is a far simpler integration than attempting to manually use the Firebase SDK (and gets you nice benefits - such as local caching).
1) Firebase Authentication
Once Firebase Authentication is initialized, FirebaseAuth.DefaultInstance.CurrentUser will always contain your currently signed in user or null if the user is not signed in. This value is actually stored in C++ and accessed through C#, meaning that it doesn't actually know about or abide by Unity's typical object lifecycles. That means that once you've signed in a user, this value will always hold the current user without the need to persist it across scene boundaries. In fact, this value is even preserved across runs of your game (meaning that your players don't have to log in every time).
A warning about this though: CurrentUser is updated asynchronously -- that is that there is no real guarantee that CurrentUser is up to date -- so it's generally safe to register a StateChanged listener as Puf suggested from the documentation:
Firebase.Auth.FirebaseAuth auth;
Firebase.Auth.FirebaseUser user;
// Handle initialization of the necessary firebase modules:
void InitializeFirebase() {
Debug.Log("Setting up Firebase Auth");
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
// Track state changes of the auth object.
void AuthStateChanged(object sender, System.EventArgs eventArgs) {
if (auth.CurrentUser != user) {
bool signedIn = user != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && user != null) {
Debug.Log("Signed out " + user.UserId);
}
user = auth.CurrentUser;
if (signedIn) {
Debug.Log("Signed in " + user.UserId);
}
}
}
void OnDestroy() {
auth.StateChanged -= AuthStateChanged;
auth = null;
}
I would highly recommend watching my tutorial on Firebase Authentication to see how I think about integrating this with a game. The link you shared is appropriate, but I'm a little curious about the various REST calls I see in your code.
If you're using the Firebase Unity SDK, email/password authentication should be as easy as:
auth.CreateUserWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
if (task.IsCanceled) {
Debug.LogError("CreateUserWithEmailAndPasswordAsync was canceled.");
return;
}
if (task.IsFaulted) {
Debug.LogError("CreateUserWithEmailAndPasswordAsync encountered an error: " + task.Exception);
return;
}
// Firebase user has been created.
Firebase.Auth.FirebaseUser newUser = task.Result;
Debug.LogFormat("Firebase user created successfully: {0} ({1})",
newUser.DisplayName, newUser.UserId);
});
to create a user and
auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
if (task.IsCanceled) {
Debug.LogError("SignInWithEmailAndPasswordAsync was canceled.");
return;
}
if (task.IsFaulted) {
Debug.LogError("SignInWithEmailAndPasswordAsync encountered an error: " + task.Exception);
return;
}
Firebase.Auth.FirebaseUser newUser = task.Result;
Debug.LogFormat("User signed in successfully: {0} ({1})",
newUser.DisplayName, newUser.UserId);
});
to sign them in. That is, there should be no need to use RestClient.
2) Realtime Database
Once you're authenticated, any calls to the Firebase Realtime Database SDK will automatically use the CurrentUser value (as I mentioned before - it persists on the C++ side of the SDK).
If you're hoping to use rules to secure user data such as:
{
"rules": {
"users": {
"$user_id": {
// grants write access to the owner of this user account
// whose uid must exactly match the key ($user_id)
".write": "$user_id === auth.uid"
}
}
}
}
Then writing data:
Database.DefaultInstance.GetReference($"/users/{FirebaseAuth.DefaultInstance.CurrentUser.UserId}/mySecret").SetValueAsync("flowers");
should just work.
I hope that all helps!
--Patrick
The Firebase SDK automatically persists the authentication state, and tries to restore it automatically too. You'll just need to write code to pick it up, which involves attaching a listener to the auth state.
See the first snippet in the Firebase documentation on getting the currently signed in user:
The recommended way to get the current user is by setting a listener on the Auth object:
Firebase.Auth.FirebaseAuth auth;
Firebase.Auth.FirebaseUser user;
// Handle initialization of the necessary firebase modules:
void InitializeFirebase() {
Debug.Log("Setting up Firebase Auth");
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
// Track state changes of the auth object.
void AuthStateChanged(object sender, System.EventArgs eventArgs) {
if (auth.CurrentUser != user) {
bool signedIn = user != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && user != null) {
Debug.Log("Signed out " + user.UserId);
}
user = auth.CurrentUser;
if (signedIn) {
Debug.Log("Signed in " + user.UserId);
}
}
}
void OnDestroy() {
auth.StateChanged -= AuthStateChanged;
auth = null;
}

WebIce Integration using Quick fix

I am newbie to fix protocol and quick fix programming. I am seeking a help on getting Trade Capture report from ICE. I have googled for the sample/ tutorial to use quick fix/n to get the trade report but I am not being able to get sufficient output of it.
My problem is to get Trade Capture report or deal information for this I tried using TradeCaptureReportRequest, TradeCaptureReportRequestAck, TradeCaptureReport classes but somehow its now working.
A simple how to extract information would be a great help.
thanking everyone out there in advance.
Ok I am posting as an answer because it's going to be way too long for a comment. Please keep in mind that I have written custom constants, message types, etc (I wrote my acceptor server as well, so I'm not restricted by ICE constants/enums). You will need to determine what fields are required by ICE and make changes - this will not be easy to copy/paste...
First, you need to make sure you have all required files in and referenced. I create a folder called "fix" in my project, and copy all fix files into it. These need to be (at least 1) FixXXX.xml file, if you're using FIX50SP1 or 2, you need to also have FIXT11.xml. Along with the .xml files, you need to have an initiator.cfg file (assuming you're making an initiator, no a server, otherwise this will need to be "acceptor.cfg" but again, it sounds like you're trying to connect to ICE, so initiator is the correct usage. Finally, you will need to have a QuickFix.dll. My tree looks as below:
I am not going to go through the XML files - you will need to just learn that - it is very confusing and takes time.. especially if using FIXT11.XML along with SP1 or 2.
Your initiator.cfg should be similar to below:
# default settings for sessions
[DEFAULT]
FileStorePath=store
FileLogPath=log
ConnectionType=initiator
ReconnectInterval=60
SenderCompID=[Enter yours]
ResetOnLogon=Y
ResetOnLogout=Y
ResetOnDisconnect=Y
[SESSION]
BeginString=FIXT.1.1
TargetCompID=[Enter ICE Acceptor]
DefaultApplVerID=FIX.5.0
StartTime=12:30:00
EndTime=21:30:00
# overide default setting for RecconnectInterval
ReconnectInterval=30
HeartBtInt=30
SocketConnectPort=[From ICE]
# (optional) only listen for incoming connections on a specific host
#SocketConnectHost=127.0.0.1
SocketConnectHost=[ICE Ip Address- from your documentation/registration]
DataDictionary=..\..\fix\FIX50.xml
TransportDataDictionary=..\..\fix\FIXT11.xml
Ok, assuming that you have QuickFix.dll imported and referenced, and your initiator.cfg properly connected, it's actually fairly simple:
Create a Class that handles everything. Ignore AddToLB, that is a testing function.
public class TCT_Fix : Control, IApplication
{
private readonly string username = [removed]
private readonly string password = [removed]
public string InitiatorID;
SessionID sessionID;
public bool running;
SessionSettings settings;
IMessageStoreFactory storeFactory;
ILogFactory logFactory;
SocketInitiator initiator;
public event EventHandler AddToLB;
public event EventHandler AddToAdmin;
public void StopIt()
{
if (sessionID == null) return;
try
{
Session.LookupSession(sessionID).Disconnect("Stopping");
settings.Remove(sessionID);
settings = null;
initiator.Dispose();
settings = new SessionSettings(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fix", "initiator.cfg"));
storeFactory = new FileStoreFactory(settings);
logFactory = new FileLogFactory(settings);
initiator = new SocketInitiator(
this,
storeFactory,
settings,
logFactory);
}
catch { }
}
public void FromApp(QuickFix.Message msg, SessionID sessionID)
{
var sMsg = "FROM APP: " + msg.ToString();
AddToLB(sMsg, null);
if (msg.Header.GetField(35) == "TC") //Cash
{
DateTime dtTdate;
float fPrice;
int Qty;
int OrdType;
bool BPisBuyer;
DateTime.TryParse(msg.GetField(CustomConstants.TDATE),out dtTdate);
string BPSide = msg.GetField(CustomConstants.BP_SIDE);
float.TryParse(msg.GetField(CustomConstants.F_PRICE), out fPrice);
int.TryParse(msg.GetField(CustomConstants.QTY), out Qty);
string TCTReference = msg.GetField(CustomConstants.TCT_REF);
string BPAcct = msg.GetField(CustomConstants.BP_COMPANY);
int.TryParse(msg.GetField(CustomConstants.ORDER_TYPE), out OrdType);
string ExecBkr = msg.GetField(CustomConstants.EXEC_BKR);
string CounterParty = msg.GetField(CustomConstants.COUNTER_PARTY);
BPisBuyer = msg.GetField(CustomConstants.IS_BUYER) == "Y";
string BPTrader = msg.GetField(CustomConstants.BP_TRADER);
string CounterTrader = msg.GetField(CustomConstants.COUNTER_TRADER);
string Grade = msg.GetField(CustomConstants.GRADE);
string Location = msg.GetField(CustomConstants.LOCATION);
string CycDt = msg.GetField(CustomConstants.CYCLE_DATE);
string DelMo = msg.GetField(CustomConstants.DELIVER_MONTH);
string Terms = msg.GetField(CustomConstants.TERMS);
string Payment = msg.GetField(CustomConstants.PAYMENT);
string Origin = msg.GetField(CustomConstants.ORIGIN);
string NumOfCyc = msg.GetField(CustomConstants.NUM_OF_CYCLES);
string Via = msg.GetField(CustomConstants.VIA);
string MoveMo = msg.GetField(CustomConstants.MOVE_MONTH);
string Comment = msg.GetField(CustomConstants.COMMENT);
}
else if (msg.Header.GetField(35) == "TE") //EFP
{
DateTime dtTdate;
float fPrice;
int Qty;
int OrdType;
bool BPisBuyer;
bool IsWater;
DateTime.TryParse(msg.GetField(CustomConstants.TDATE), out dtTdate);
string BPSide = msg.GetField(CustomConstants.BP_SIDE);
float.TryParse(msg.GetField(CustomConstants.F_PRICE), out fPrice);
int.TryParse(msg.GetField(CustomConstants.QTY), out Qty);
string TCTReference = msg.GetField(CustomConstants.TCT_REF);
string BPAcct = msg.GetField(CustomConstants.BP_COMPANY);
int.TryParse(msg.GetField(CustomConstants.ORDER_TYPE), out OrdType);
string ExecBkr = msg.GetField(CustomConstants.EXEC_BKR);
string CounterParty = msg.GetField(CustomConstants.COUNTER_PARTY);
BPisBuyer = msg.GetField(CustomConstants.IS_BUYER) == "Y";
string BPTrader = msg.GetField(CustomConstants.BP_TRADER);
string CounterTrader = msg.GetField(CustomConstants.COUNTER_TRADER);
string Grade = msg.GetField(CustomConstants.GRADE);
string Location = msg.GetField(CustomConstants.LOCATION);
string CycDt = msg.GetField(CustomConstants.CYCLE_DATE);
string DelMo = msg.GetField(CustomConstants.DELIVER_MONTH);
string Terms = msg.GetField(CustomConstants.TERMS);
string Payment = msg.GetField(CustomConstants.PAYMENT);
string Origin = msg.GetField(CustomConstants.ORIGIN);
string NumOfCyc = msg.GetField(CustomConstants.NUM_OF_CYCLES);
string Via = msg.GetField(CustomConstants.VIA);
string MoveMo = msg.GetField(CustomConstants.MOVE_MONTH);
string Comment = msg.GetField(CustomConstants.COMMENT);
IsWater = msg.GetField(CustomConstants.ISWATER) == "Y";
string BPFloorBkr = msg.GetField(CustomConstants.BP_FLOOR_BKR);
string CounterFloorBkr = msg.GetField(CustomConstants.COUNTER_FLOOR_BKR);
string Diff = msg.GetField(CustomConstants.DIFFERENCE);
string MercMo = msg.GetField(CustomConstants.MERC_MO);
string MercPr = msg.GetField(CustomConstants.MERC_PRICE);
}
else if (msg.Header.GetField(35) == "TI") //Index
{
DateTime dtTdate;
float fPrice;
int Qty;
int OrdType;
bool BPisBuyer;
bool IsWater;
DateTime.TryParse(msg.GetField(CustomConstants.TDATE), out dtTdate);
string BPSide = msg.GetField(CustomConstants.BP_SIDE);
float.TryParse(msg.GetField(CustomConstants.F_PRICE), out fPrice);
int.TryParse(msg.GetField(CustomConstants.QTY), out Qty);
string TCTReference = msg.GetField(CustomConstants.TCT_REF);
string BPAcct = msg.GetField(CustomConstants.BP_COMPANY);
int.TryParse(msg.GetField(CustomConstants.ORDER_TYPE), out OrdType);
string ExecBkr = msg.GetField(CustomConstants.EXEC_BKR);
string CounterParty = msg.GetField(CustomConstants.COUNTER_PARTY);
BPisBuyer = msg.GetField(CustomConstants.IS_BUYER) == "Y";
string BPTrader = msg.GetField(CustomConstants.BP_TRADER);
string CounterTrader = msg.GetField(CustomConstants.COUNTER_TRADER);
string Grade = msg.GetField(CustomConstants.GRADE);
string Location = msg.GetField(CustomConstants.LOCATION);
string CycDt = msg.GetField(CustomConstants.CYCLE_DATE);
string DelMo = msg.GetField(CustomConstants.DELIVER_MONTH);
string Terms = msg.GetField(CustomConstants.TERMS);
string Payment = msg.GetField(CustomConstants.PAYMENT);
string Origin = msg.GetField(CustomConstants.ORIGIN);
string NumOfCyc = msg.GetField(CustomConstants.NUM_OF_CYCLES);
string Via = msg.GetField(CustomConstants.VIA);
string MoveMo = msg.GetField(CustomConstants.MOVE_MONTH);
string Comment = msg.GetField(CustomConstants.COMMENT);
IsWater = msg.GetField(CustomConstants.ISWATER) == "Y";
string BPFloorBkr = msg.GetField(CustomConstants.BP_FLOOR_BKR);
string CounterFloorBkr = msg.GetField(CustomConstants.COUNTER_FLOOR_BKR);
string Diff = msg.GetField(CustomConstants.DIFFERENCE);
string MercMo = msg.GetField(CustomConstants.MERC_MO);
string MercPr = msg.GetField(CustomConstants.MERC_PRICE);
}
}
public void OnCreate(SessionID sessionID)
{
AddToAdmin("SESSION CREATED: " + sessionID.ToString(), null);
}
public void OnLogout(SessionID sessionID)
{
AddToAdmin("LOGOUT: " + this.sessionID.ToString(), null);
}
public void OnLogon(SessionID sessionID)
{
this.sessionID = sessionID;
AddToAdmin("LOG ON: " + this.sessionID.ToString(),null);
}
public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
{
AddToAdmin("FROM ADMIN: " + msg.ToString(), null);
}
public void ToAdmin(QuickFix.Message msg, SessionID sessionID)
{
if (msg.Header.GetField(35).ToString() == "A")
{
msg.SetField(new QuickFix.Fields.Username(username));
msg.SetField(new QuickFix.Fields.Password(password));
}
AddToAdmin("TO ADMIN: " + msg.ToString(), null);
}
public void ToApp(QuickFix.Message msg, SessionID sessionID)
{
AddToLB("TO APP: " + msg.ToString(), null);
}
public void GetTestMessage(string msgType)
{
if (sessionID == null) return;
QuickFix.FIX50.TestMessage msg = new QuickFix.FIX50.TestMessage();
msg.TestType = msgType;
msg.Header.SetField(new QuickFix.Fields.MsgType("TEST"));
msg.SetField(new QuickFix.Fields.StringField(CustomConstants.TEST_TYPE, msgType));
Session.SendToTarget(msg, sessionID);
}
public TCT_Fix()
{
settings = new SessionSettings(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fix", "initiator.cfg"));
storeFactory = new FileStoreFactory(settings);
logFactory = new FileLogFactory(settings);
initiator = new SocketInitiator(
this,
storeFactory,
settings,
logFactory);
}
public TCT_Fix(ref string initID)
{
InitiatorID = initID;
settings = new SessionSettings(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fix", "initiator.cfg"));
storeFactory = new FileStoreFactory(settings);
logFactory = new FileLogFactory(settings);
initiator = new SocketInitiator(
this,
storeFactory,
settings,
logFactory);
}
public void RunIt()
{
if (running) return;
if(initiator.IsStopped)
{
try
{
initiator.Start(); //This can throw an error due to current set up. I would recommend making the connection,
//pulling data, and then closing the connection (polling) to ensure the initiator clears the
//log files
//reference http://lists.quickfixn.com/pipermail/quickfixn-quickfixn.com/2013q1/000747.html
//2013 issue, still unresolved... Restart app
}
catch(Exception ex)
{
if (MessageBox.Show("Error restarting initiator. Program will close due to file access. This is a Quickfix bug, not an issue with this program. Please restart." + Environment.NewLine + Environment.NewLine +
"Reference: http://lists.quickfixn.com/pipermail/quickfixn-quickfixn.com/2013q1/000747.html for more information. Click ok to copy link to clipboard. Click \"X\" to ignore.") == DialogResult.OK)
{
Clipboard.SetText("http://lists.quickfixn.com/pipermail/quickfixn-quickfixn.com/2013q1/000747.html");
}
throw new Exception(ex.ToString());
}
}
running = true;
}
}
Finally, to make it stand out (this is actually in the block above as well), you construct a message similar to below, keeping in mind that your ICE Message will have certain required fields that my "TestMessage" does not. I cannot give code from production though - sorry.
public void GetTestMessage(string msgType)
{
if (sessionID == null) return;
QuickFix.FIX50.TestMessage msg = new QuickFix.FIX50.TestMessage();
msg.TestType = msgType;
msg.Header.SetField(new QuickFix.Fields.MsgType("TEST"));
msg.SetField(new QuickFix.Fields.StringField(CustomConstants.TEST_TYPE, msgType));
Session.SendToTarget(msg, sessionID);
}
The learning curve is substantial. You will just need to keep playing around until you get it. Once you get it down though, it makes sense. Stick with it. Let me know if you need anything else.

Implementing Overrides in Bloomberg C# API

In querying "YAS_YLD_SPREAD" for multiple securities, I am trying to assign a different override value for the "YAS_BOND_PX" override of each (as per Excel snapshot)
However, I am doing something wrong in assigning the overrides, as the output does not return a single "YAS_YLD_SPREAD" for each security (it also spuriously returns a "YAS_YLD_SPREAD 1") and the values returned are not the 100.21, 645.06 values I expect/need
Grateful for your help,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ArrayList = System.Collections.ArrayList;
using Event = Bloomberglp.Blpapi.Event;
using Element = Bloomberglp.Blpapi.Element;
using Message = Bloomberglp.Blpapi.Message;
using Name = Bloomberglp.Blpapi.Name;
using Request = Bloomberglp.Blpapi.Request;
using Service = Bloomberglp.Blpapi.Service;
using Session = Bloomberglp.Blpapi.Session;
using SessionOptions = Bloomberglp.Blpapi.SessionOptions;
using InvalidRequestException =
Bloomberglp.Blpapi.InvalidRequestException;
using Subscription = Bloomberglp.Blpapi.Subscription;
namespace COATI
{
public class BloombergFetch
{
public string[] IsinArray;
private const String APIREFDATA_SVC = "//blp/refdata";
private static readonly Name SECURITY_DATA =
Name.GetName("securityData");
private static readonly Name SECURITY = Name.GetName("security");
private static readonly Name FIELD_DATA = Name.GetName("fieldData");
private static readonly Name RESPONSE_ERROR =
Name.GetName("responseError");
private static readonly Name SECURITY_ERROR =
Name.GetName("securityError");
private static readonly Name FIELD_EXCEPTIONS =
Name.GetName("fieldExceptions");
private static readonly Name FIELD_ID = Name.GetName("fieldId");
private static readonly Name ERROR_INFO = Name.GetName("errorInfo");
private static readonly Name CATEGORY = Name.GetName("category");
private static readonly Name MESSAGE = Name.GetName("message");
private ArrayList d_securities = new ArrayList();
private ArrayList d_fields = new ArrayList();
private ArrayList d_overrides = new ArrayList();
private ArrayList d_overridevalues = new ArrayList();
static void Main()
{
BloombergFetch example = new BloombergFetch();
example.run();
System.Console.WriteLine("Press ENTER to quit");
System.Console.Read();
}
public void run()
{
string serverHost = "localhost";
int serverPort = 8194;
SessionOptions sessionOptions = new SessionOptions();
sessionOptions.ServerHost = serverHost;
sessionOptions.ServerPort = serverPort;
System.Console.WriteLine("Connecting to " + serverHost + ":" +
serverPort);
Session session = new Session(sessionOptions);
bool sessionStarted = session.Start();
if (!sessionStarted)
{
System.Console.Error.WriteLine("Failed to start session.");
return;
}
d_securities.Add("XS0975256685 Corp");
d_securities.Add("XS1207058733 Corp");
d_fields.Add("YAS_YLD_SPREAD");
d_fields.Add("YAS_YLD_SPREAD");
d_overrides.Add("YAS_BOND_PX"); d_overridevalues.Add(116);
d_overrides.Add("YAS_BOND_PX"); d_overridevalues.Add(88);
try
{
sendRefDataRequest(session);
}
catch (InvalidRequestException e)
{
System.Console.WriteLine(e.ToString());
}
// wait for events from session.
eventLoop(session);
session.Stop();
*/
}
private void sendRefDataRequest(Session session)
{
if (!session.OpenService(APIREFDATA_SVC))
{
System.Console.Error.WriteLine("Failed to open service: " +
APIREFDATA_SVC);
return;
}
Service refDataService = session.GetService(APIREFDATA_SVC);
Request request = refDataService.CreateRequest("ReferenceDataRequest");
Element securities = request.GetElement("securities");
Element overrides = request.GetElement("overrides");
for (int i = 0; i < d_securities.Count; ++i)
{
securities.AppendValue((string)d_securities[i]);
}
Element fields = request.GetElement("fields");
for (int i = 0; i < d_fields.Count; ++i)
{
fields.AppendValue((string)d_fields[i]);
}
for (int i = 0; i < d_overrides.Count; ++i)
{
Element bboverride = overrides.AppendElement();
bboverride.SetElement("fieldId",d_overrides[i].ToString());
//bboverride.SetElement("fieldId", "YAS_BOND_PX");
bboverride.SetElement("value", Convert.ToBoolean(d_overridevalues[i]));
//bboverride.SetElement("value", 100);
}
System.Console.WriteLine("Sending Request: " + request);
session.SendRequest(request, null);
}
private void eventLoop(Session session)
{
bool done = false;
while (!done)
{
Event eventObj = session.NextEvent();
if (eventObj.Type == Event.EventType.PARTIAL_RESPONSE)
{
System.Console.WriteLine("Processing Partial Response");
processResponseEvent(eventObj);
}
else if (eventObj.Type == Event.EventType.RESPONSE)
{
System.Console.WriteLine("Processing Response");
processResponseEvent(eventObj);
done = true;
}
else
{
foreach (Message msg in eventObj.GetMessages())
{
System.Console.WriteLine(msg.AsElement);
if (eventObj.Type == Event.EventType.SESSION_STATUS)
{
if (msg.MessageType.Equals("SessionTerminated"))
{
done = true;
}
}
}
}
}
}
private void processResponseEvent(Event eventObj)
{
foreach (Message msg in eventObj.GetMessages())
{
if (msg.HasElement(RESPONSE_ERROR))
{
System.Console.WriteLine("REQUEST FAILED: " +
msg.GetElement(RESPONSE_ERROR));
continue;
}
Element securities = msg.GetElement(SECURITY_DATA);
int numSecurities = securities.NumValues;
System.Console.WriteLine("Processing " + numSecurities + " securities:");
for (int i = 0; i < numSecurities; ++i)
{
Element security = securities.GetValueAsElement(i);
string ticker = security.GetElementAsString(SECURITY);
System.Console.WriteLine("\nTicker: " + ticker);
if (security.HasElement("securityError"))
{
System.Console.WriteLine("\tSECURITY FAILED: " +
security.GetElement(SECURITY_ERROR));
continue;
}
Element fields = security.GetElement(FIELD_DATA);
if (fields.NumElements > 0)
{
System.Console.WriteLine("FIELD\t\tVALUE");
System.Console.WriteLine("-----\t\t-----");
int numElements = fields.NumElements;
for (int j = 0; j < numElements; ++j)
{
Element field = fields.GetElement(j);
System.Console.WriteLine(field.Name + "\t\t" +
field.GetValueAsString());
}
}
else System.Console.WriteLine("No fields");
}
}
}
}
}
I haven't read your code in detail but one obvious issue is that if you want to use a different overriden value for the two securities, you need to submit two separate requests.
If you submit one request for XS0975256685 only with the YAS_BOND_PX override set to 116, you should get the desired result (I got 101.8739 a minute ago which matches Excel's result at the same moment).
Also note that the returned value does change with the market so you may get different values at each run: refresh your Excel spreadsheet at the same time if you want to verify that the data match.

EntityTooSmall in CompleteMultipartUploadResponse

using .NET SDK v.1.5.21.0
I'm trying to upload a large file (63Mb) and I'm following the example at:
http://docs.aws.amazon.com/AmazonS3/latest/dev/LLuploadFileDotNet.html
But using a helper instead the hole code and using jQuery File Upload
https://github.com/blueimp/jQuery-File-Upload/blob/master/basic-plus.html
what I have is:
string bucket = "mybucket";
long totalSize = long.Parse(context.Request.Headers["X-File-Size"]),
maxChunkSize = long.Parse(context.Request.Headers["X-File-MaxChunkSize"]),
uploadedBytes = long.Parse(context.Request.Headers["X-File-UloadedBytes"]),
partNumber = uploadedBytes / maxChunkSize + 1,
fileSize = partNumber * inputStream.Length;
bool lastPart = inputStream.Length < maxChunkSize;
// http://docs.aws.amazon.com/AmazonS3/latest/dev/LLuploadFileDotNet.html
if (partNumber == 1) // initialize upload
{
iView.Utilities.Amazon_S3.S3MultipartUpload.InitializePartToCloud(fileName, bucket);
}
try
{
// upload part
iView.Utilities.Amazon_S3.S3MultipartUpload.UploadPartToCloud(fs, fileName, bucket, (int)partNumber, uploadedBytes, maxChunkSize);
if (lastPart)
// wrap it up and go home
iView.Utilities.Amazon_S3.S3MultipartUpload.CompletePartToCloud(fileName, bucket);
}
catch (System.Exception ex)
{
// Huston, we have a problem!
//Console.WriteLine("Exception occurred: {0}", exception.Message);
iView.Utilities.Amazon_S3.S3MultipartUpload.AbortPartToCloud(fileName, bucket);
}
and
public static class S3MultipartUpload
{
private static string accessKey = System.Configuration.ConfigurationManager.AppSettings["AWSAccessKey"];
private static string secretAccessKey = System.Configuration.ConfigurationManager.AppSettings["AWSSecretKey"];
private static AmazonS3 client = Amazon.AWSClientFactory.CreateAmazonS3Client(accessKey, secretAccessKey);
public static InitiateMultipartUploadResponse initResponse;
public static List<UploadPartResponse> uploadResponses;
public static void InitializePartToCloud(string destinationFilename, string destinationBucket)
{
// 1. Initialize.
uploadResponses = new List<UploadPartResponse>();
InitiateMultipartUploadRequest initRequest =
new InitiateMultipartUploadRequest()
.WithBucketName(destinationBucket)
.WithKey(destinationFilename.TrimStart('/'));
initResponse = client.InitiateMultipartUpload(initRequest);
}
public static void UploadPartToCloud(Stream fileStream, string destinationFilename, string destinationBucket, int partNumber, long uploadedBytes, long maxChunkedBytes)
{
// 2. Upload Parts.
UploadPartRequest request = new UploadPartRequest()
.WithBucketName(destinationBucket)
.WithKey(destinationFilename.TrimStart('/'))
.WithUploadId(initResponse.UploadId)
.WithPartNumber(partNumber)
.WithPartSize(maxChunkedBytes)
.WithFilePosition(uploadedBytes)
.WithInputStream(fileStream) as UploadPartRequest;
uploadResponses.Add(client.UploadPart(request));
}
public static void CompletePartToCloud(string destinationFilename, string destinationBucket)
{
// Step 3: complete.
CompleteMultipartUploadRequest compRequest =
new CompleteMultipartUploadRequest()
.WithBucketName(destinationBucket)
.WithKey(destinationFilename.TrimStart('/'))
.WithUploadId(initResponse.UploadId)
.WithPartETags(uploadResponses);
CompleteMultipartUploadResponse completeUploadResponse =
client.CompleteMultipartUpload(compRequest);
}
public static void AbortPartToCloud(string destinationFilename, string destinationBucket)
{
// abort.
client.AbortMultipartUpload(new AbortMultipartUploadRequest()
.WithBucketName(destinationBucket)
.WithKey(destinationFilename.TrimStart('/'))
.WithUploadId(initResponse.UploadId));
}
}
my maxChunckedSize is 6Mb (6 * (1024*1024)) as I have read that the minimum is 5Mb...
why am I getting "Your proposed upload is smaller than the minimum allowed size" exception? What am I doing wrong?
The error is:
<Error>
<Code>EntityTooSmall</Code>
<Message>Your proposed upload is smaller than the minimum allowed size</Message>
<ETag>d41d8cd98f00b204e9800998ecf8427e</ETag>
<MinSizeAllowed>5242880</MinSizeAllowed>
<ProposedSize>0</ProposedSize>
<RequestId>C70E7A23C87CE5FC</RequestId>
<HostId>pmhuMXdRBSaCDxsQTHzucV5eUNcDORvKY0L4ZLMRBz7Ch1DeMh7BtQ6mmfBCLPM2</HostId>
<PartNumber>1</PartNumber>
</Error>
How can I get ProposedSize if I'm passing the stream and stream length?
Here is a working solution for the latest Amazon SDK (as today: v.1.5.37.0)
Amazon S3 Multipart Upload works like:
Initialize the request using client.InitiateMultipartUpload(initRequest)
Send chunks of the file (loop until the end) using client.UploadPart(request)
Complete the request using client.CompleteMultipartUpload(compRequest)
If anything goes wrong, remember to dispose the client and request, as well fire the abort command using client.AbortMultipartUpload(abortMultipartUploadRequest)
I keep the client in Session as we need this for each chunk upload as well, keep an hold of the ETags that are now used to complete the process.
You can see an example and simple way of doing this in Amazon Docs itself, I ended up having a class to do everything, plus, I have integrated with the lovely jQuery File Upload plugin (Handler code below as well).
The S3MultipartUpload is as follow
public class S3MultipartUpload : IDisposable
{
string accessKey = System.Configuration.ConfigurationManager.AppSettings.Get("AWSAccessKey");
string secretAccessKey = System.Configuration.ConfigurationManager.AppSettings.Get("AWSSecretKey");
AmazonS3 client;
public string OriginalFilename { get; set; }
public string DestinationFilename { get; set; }
public string DestinationBucket { get; set; }
public InitiateMultipartUploadResponse initResponse;
public List<PartETag> uploadPartETags;
public string UploadId { get; private set; }
public S3MultipartUpload(string destinationFilename, string destinationBucket)
{
if (client == null)
{
System.Net.WebRequest.DefaultWebProxy = null; // disable proxy to make upload quicker
client = Amazon.AWSClientFactory.CreateAmazonS3Client(accessKey, secretAccessKey, new AmazonS3Config()
{
RegionEndpoint = Amazon.RegionEndpoint.EUWest1,
CommunicationProtocol = Protocol.HTTP
});
this.OriginalFilename = destinationFilename.TrimStart('/');
this.DestinationFilename = string.Format("{0:yyyy}{0:MM}{0:dd}{0:HH}{0:mm}{0:ss}{0:fffff}_{1}", DateTime.UtcNow, this.OriginalFilename);
this.DestinationBucket = destinationBucket;
this.InitializePartToCloud();
}
}
private void InitializePartToCloud()
{
// 1. Initialize.
uploadPartETags = new List<PartETag>();
InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest();
initRequest.BucketName = this.DestinationBucket;
initRequest.Key = this.DestinationFilename;
// make it public
initRequest.AddHeader("x-amz-acl", "public-read");
initResponse = client.InitiateMultipartUpload(initRequest);
}
public void UploadPartToCloud(Stream fileStream, long uploadedBytes, long maxChunkedBytes)
{
int partNumber = uploadPartETags.Count() + 1; // current part
// 2. Upload Parts.
UploadPartRequest request = new UploadPartRequest();
request.BucketName = this.DestinationBucket;
request.Key = this.DestinationFilename;
request.UploadId = initResponse.UploadId;
request.PartNumber = partNumber;
request.PartSize = fileStream.Length;
//request.FilePosition = uploadedBytes // remove this line?
request.InputStream = fileStream; // as UploadPartRequest;
var up = client.UploadPart(request);
uploadPartETags.Add(new PartETag() { ETag = up.ETag, PartNumber = partNumber });
}
public string CompletePartToCloud()
{
// Step 3: complete.
CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest();
compRequest.BucketName = this.DestinationBucket;
compRequest.Key = this.DestinationFilename;
compRequest.UploadId = initResponse.UploadId;
compRequest.PartETags = uploadPartETags;
string r = "Something went badly wrong";
using (CompleteMultipartUploadResponse completeUploadResponse = client.CompleteMultipartUpload(compRequest))
r = completeUploadResponse.ResponseXml;
return r;
}
public void AbortPartToCloud()
{
// abort.
client.AbortMultipartUpload(new AbortMultipartUploadRequest()
{
BucketName = this.DestinationBucket,
Key = this.DestinationFilename,
UploadId = initResponse.UploadId
});
}
public void Dispose()
{
if (client != null) client.Dispose();
if (initResponse != null) initResponse.Dispose();
}
}
I use DestinationFilename as the destination file so I can avoid the same name, but I keep the OriginalFilename as I needed later.
Using jQuery File Upload Plugin, all works inside a Generic Handler, and the process is something like this:
// Upload partial file
private void UploadPartialFile(string fileName, HttpContext context, List<FilesStatus> statuses)
{
if (context.Request.Files.Count != 1)
throw new HttpRequestValidationException("Attempt to upload chunked file containing more than one fragment per request");
var inputStream = context.Request.Files[0].InputStream;
string contentRange = context.Request.Headers["Content-Range"]; // "bytes 0-6291455/14130271"
int fileSize = int.Parse(contentRange.Split('/')[1]);,
maxChunkSize = int.Parse(context.Request.Headers["X-Max-Chunk-Size"]),
uploadedBytes = int.Parse(contentRange.Replace("bytes ", "").Split('-')[0]);
iView.Utilities.AWS.S3MultipartUpload s3Upload = null;
try
{
// ######################################################################################
// 1. Initialize Amazon S3 Client
if (uploadedBytes == 0)
{
HttpContext.Current.Session["s3-upload"] = new iView.Utilities.AWS.S3MultipartUpload(fileName, awsBucket);
s3Upload = (iView.Utilities.AWS.S3MultipartUpload)HttpContext.Current.Session["s3-upload"];
string msg = System.String.Format("Upload started: {0} ({1:N0}Mb)", s3Upload.DestinationFilename, (fileSize / 1024));
this.Log(msg);
}
// cast current session object
if (s3Upload == null)
s3Upload = (iView.Utilities.AWS.S3MultipartUpload)HttpContext.Current.Session["s3-upload"];
// ######################################################################################
// 2. Send Chunks
s3Upload.UploadPartToCloud(inputStream, uploadedBytes, maxChunkSize);
// ######################################################################################
// 3. Complete Upload
if (uploadedBytes + maxChunkSize > fileSize)
{
string completeRequest = s3Upload.CompletePartToCloud();
this.Log(completeRequest); // log S3 response
s3Upload.Dispose(); // dispose all objects
HttpContext.Current.Session["s3-upload"] = null; // we don't need this anymore
}
}
catch (System.Exception ex)
{
if (ex.InnerException != null)
while (ex.InnerException != null)
ex = ex.InnerException;
this.Log(string.Format("{0}\n\n{1}", ex.Message, ex.StackTrace)); // log error
s3Upload.AbortPartToCloud(); // abort current upload
s3Upload.Dispose(); // dispose all objects
statuses.Add(new FilesStatus(ex.Message));
return;
}
statuses.Add(new FilesStatus(s3Upload.DestinationFilename, fileSize, ""));
}
Keep in mind that to have a Session object inside a Generic Handler, you need to implement IRequiresSessionState so your handler will look like:
public class UploadHandlerSimple : IHttpHandler, IRequiresSessionState
Inside fileupload.js (under _initXHRData) I have added an extra header called X-Max-Chunk-Size so I can pass this to Amazon and calculate if it's the last part of the uploaded file.
Fell free to comment and make smart edits for everyone to use.
I guess you didn't set the content-length of the part inside the UploadPartToCloud() function.

spamassassin check score C# code

Is there a way to check the score in an ASP.Net application? A class or something similar for .Net? How about other Spam Filters out there.
--Edited
I am looking for a way to check the spam score of the email messages in C#.
Here is my super simplified "just check the score" code for connecting to a running Spam Assassin email check from C# which I wrote for http://elasticemail.com. Just setup SA to run on a server and set the access permissions.
Then you can use this code to call it:
public class SimpleSpamAssassin
{
public class RuleResult
{
public double Score = 0;
public string Rule = "";
public string Description = "";
public RuleResult() { }
public RuleResult(string line)
{
Score = double.Parse(line.Substring(0, line.IndexOf(" ")).Trim());
line = line.Substring(line.IndexOf(" ") + 1);
Rule = line.Substring(0, 23).Trim();
Description = line.Substring(23).Trim();
}
}
public static List<RuleResult> GetReport(string serverIP, string message)
{
string command = "REPORT";
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0} SPAMC/1.2\r\n", command);
sb.AppendFormat("Content-Length: {0}\r\n\r\n", message.Length);
sb.AppendFormat(message);
byte[] messageBuffer = Encoding.ASCII.GetBytes(sb.ToString());
using (Socket spamAssassinSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
spamAssassinSocket.Connect(serverIP, 783);
spamAssassinSocket.Send(messageBuffer);
spamAssassinSocket.Shutdown(SocketShutdown.Send);
int received;
string receivedMessage = string.Empty;
do
{
byte[] receiveBuffer = new byte[1024];
received = spamAssassinSocket.Receive(receiveBuffer);
receivedMessage += Encoding.ASCII.GetString(receiveBuffer, 0, received);
}
while (received > 0);
spamAssassinSocket.Shutdown(SocketShutdown.Both);
return ParseResponse(receivedMessage);
}
}
private static List<RuleResult> ParseResponse(string receivedMessage)
{
//merge line endings
receivedMessage = receivedMessage.Replace("\r\n", "\n");
receivedMessage = receivedMessage.Replace("\r", "\n");
string[] lines = receivedMessage.Split('\n');
List<RuleResult> results = new List<RuleResult>();
bool inReport = false;
foreach (string line in lines)
{
if (inReport)
{
try
{
results.Add(new RuleResult(line.Trim()));
}
catch
{
//past the end of the report
}
}
if (line.StartsWith("---"))
inReport = true;
}
return results;
}
}
Usage is quite easy:
List<RuleResult> spamCheckResult = SimpleSpamAssassin.GetReport(IP OF SA Server, FULL Email including headers);
It will return the list of spam check rules you hit and the resulting score impact.
I am not exactly sure if that's what you are searching for, but there is a C# wrapper that simplifies the communication with a SpamAssassin server on Code Project:
A C# Wrapper for the SpamAssassin Protocol
Hope that helps!

Categories