I am trying to create a bot that reads the direct messages using websocket, to avoid the ratelimit.
The problem is I don`t know much about websocket.
I googled a bit and I found some code and I used it but it don't receive anything but empty text.
This is my code
Dim ws = New System.Net.WebSockets.ClientWebSocket
ServicePointManager.ServerCertificateValidationCallback = Function(s, c, h, d) True
With ws.Options
.SetRequestHeader("Origin", "https://www.instagram.com")
.SetRequestHeader("Cookie", "don`t care about this")
End With
Try
Await ws.ConnectAsync(New Uri("wss://edge-chat.instagram.com/chat"), Nothing)
Console.WriteLine("state: " & ws.State.ToString)
If (ws.State = WebSockets.WebSocketState.Open) Then
Console.WriteLine("state: " & ws.State.ToString)
Dim bytes(4096) As Byte
Dim answ = New ArraySegment(Of Byte)(bytes)
Await ws.ReceiveAsync(answ, Nothing)
Console.WriteLine("answer:" + Text.Encoding.UTF8.GetString(answ.Array))
Else
Console.WriteLine("Not opened?!")
End If
Catch e As Exception
Console.WriteLine("Error." & e.Message)
End Try
Console.ReadLine()
End Function
I see the request in the httpdebugger but I don't know why I don't get any data.
Is the problem in my code or have I misunderstood websocket.
Related
As (hopefully) all developers, I've developed over the years and am now at the point that OOP and functional programming is a daily costs. Recently I've bumped into and "old" (2 years) DLL of my that reads in a TCP stream, drops the incoming string (which end with a line feed) into a ConcurrentQueue(Of String). Then a second Backgroundworker loops over the ConcurrentQueue(Of String) and dequeue's the string and parses it.
Depending on the request command i send to the TCP server i gat get one line or several hunders of line. Also when nothing is asked the TCP server send's nothing. It is completely event driven.
With the new and efficient Technics of PLINQ, Async/Await and TPL i am determine to make this faster/more efficient. Currently i'm brainstorming on how to do this and am asking you to think with me or give some good advice.
So let's dig deeper into what i have now:
It al starts with two Backgroundworkers, One for Reading and One for Parsing.
The Reading Backgroundworker:
This backgroundworker job is to read the incomming data and make sure to keep reading until a Linefeed is passed. Then it cuts into a string and drops it into a ConcurrentQueue(Of String). The code looks like this:
Private Sub bgwReceive_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgwTCP_Receive.DoWork
Dim strRXData As String = String.Empty
Dim intLfpos As Integer = 0
Try
Do Until bgwTCP_Receive.CancellationPending
'while the client is connected, continue to wait for and read data
While _Client.Connected AndAlso _ClientStream.CanRead
Dim buffer(_Client.ReceiveBufferSize - 1) As Byte
Dim read As Integer = _ClientStream.Read(buffer, 0, buffer.Length)
'Put the new data in the queue
If read > 0 Then
'Add incomming data to the buffer string
strRXData &= Text.Encoding.ASCII.GetString(buffer, 0, read)
'Replace "0 padding"
strRXData.Replace(Chr(0), String.Empty)
'Now check if we have a Linefeed in our buffer string
While strRXData <> String.Empty
'Get the position of the first linefeed
intLfpos = strRXData.IndexOf(vbLf)
'Now check if we find something.
If intLfpos < 0 Then Exit While
'There is a line feed, it is time to add it to the incomming data queue
IncommingData.Enqueue(strRXData.Substring(0, intLfpos - 1))
'Now remove the command from the buffer string
strRXData = strRXData.Substring(intLfpos + 1, strRXData.Length - intLfpos - 1)
End While
End If
'Check if we have to stop
If bgwTCP_Receive.CancellationPending Then e.Cancel = True : Exit Do
Threading.Thread.Sleep(1)
End While
Threading.Thread.Sleep(100)
Loop
e.Cancel = True
Catch op As OperationCanceledException
Throw New Exception("TCP Reading cancelled")
Catch se As SocketException
Throw New Exception("Socket unknown error. Native error code: " & se.NativeErrorCode)
Catch IOex As IOException
Throw New Exception("Socket timeout while receiving data from [" & TCP_ServerIP.ToString & "]")
End Try
End Sub
The Parsing Backgroundworker: This backgroundworker job is to parse the strings in the ConcurrentQueue(Of String). In this backgroundworker there is a big Select case that looks at the first word in the string. This determines what to do.
The received protocol is very simple but unfortunately it hasn't a sollid structure like JSON. A string would look like this: IND PARM1:"Hello world!" PARM2:1.4.8 \CrLf
As you can see it is very simple and plain. The IND indicate the Command, like VER is for VERSION string. IND is always 3 chars long. Then comes the parameters. The parameter name is always 4 chars long. If it is between double quotes it is a string, else its something like a double/integer/IP address (X.X.X.X). Keep in mind that original it is a string. In my parser i parse it to the object properties. The code looks like this:
Private Sub bgwProcessQueue_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgwProcessQueue.DoWork
Dim strNewLine As String = String.Empty
Dim strSubLine As String = String.Empty
Try
'Loop until program has stopped
Do Until bgwProcessQueue.CancellationPending
'Only process when something is in the queue
If TCP_Connection.IncommingData.TryDequeue(strNewLine) Then
'If Backgroundworker has to cancel than cancel
If bgwProcessQueue.CancellationPending Then Exit Do
Select Case True
Case strNewLine.StartsWith("VER") 'Example: VER PRM1:1.1 PRM2:"Hi there" PRM3:1.1.1 PRM4:8/0 PRM5:8
'First check if all the needed values are there, if not resend the command
If strNewLine.Contains("PRM1:") AndAlso strNewLine.Contains("PRM2:") AndAlso strNewLine.Contains("PRM3:") AndAlso strNewLine.Contains("PRM4:") AndAlso strNewLine.Contains("PRM5:") Then
'Get versions and devicename
Me.Param1 = GetSubstring(strNewLine, "PRM1:", " ")
Me.Param2 = GetSubstring(strNewLine, "PRM2:", " ")
Me.Param3 = GetSubstring(strNewLine, "PRM3:", " ")
Me.Param4 = GetSubstring(strNewLine, "PRM4:", " ")
Me.Param5 = GetSubstring(strNewLine, "PRM5:", " ")
Else
'Commando was invalid, resend the command
Log.Message(LogLevel.Warning, "VER Messages was incompleet, resending VER command")
SendData("VER")
End If
Case strNewLine.StartsWith("ERROR")
Log.Message(LogLevel.Warning, strNewLine)
End Select
End If
'Clear any old data
strNewLine = String.Empty
'Sleep
Threading.Thread.Sleep(1)
Loop
e.Cancel = True
Catch ex As Exception
Log.Exception(ex)
End Try
End Sub
Private Function GetSubstring(text As String, StartValue As String, EndValue As String) As String
Try
'If we can't find the Start value we can't do anything
If Not text.Contains(StartValue) Then Return String.Empty
'Find the index of the Start and End value
intStartValueIndex = text.IndexOf(StartValue) + StartValue.Length
intEndValueIndex = text.IndexOf(EndValue, intStartValueIndex)
'If no Endvalue index was found then get the end of the string
If intEndValueIndex < intStartValueIndex Then intEndValueIndex = text.Length
'Return the substring en remove quetes
Return text.Substring(intStartValueIndex, intEndValueIndex - intStartValueIndex).Replace("""", "")
Catch ex As Exception
Log.Exception(ex)
Return String.Empty
End Try
End Function
Hopefully all above is understandable. I was thinking of looping through the ConcurrentQueue(Of String) with a Parrallel.ForEach Wich passes the Dequeued string into a sub that does the parsing. At the reading side, my inspiration is empty at the moment...
I try to send command to a device and read data back via serial port, however it gives me a weird behavior. I have to sendData() a couple of times(most twice) to get the data. I do not want to use writeLine and I do not write a loop in my code (I have figured out already). My schema works like this. I set ReceivedByteThreshold to 1, so that each time the it receives the data from the device, the ReceivedData event handler is fired. I read one byte at a time. When it read CR, whose ascii is 13, I display the data on the label, but I have to send data (*idn?) more than once(sometimes can be done in one time but not consistent). See the pic for reference. I am not sure why it happens. Thank you in advance
Private Sub DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
Dim ret As Integer
ret = SerialPort.ReadByte()
If ((ret <> 13) And (ret <> 10)) Then
str &= System.Convert.ToChar(ret)
End If
If ret = 13 Then
ret = SerialPort.ReadByte()
If ret = 10 Then
Me.Label2.Text = str
str = ""
End If
End If
End Sub
Sub SendData(ByVal data As String)
Try
SerialPort.Write(data)
Catch ex As Exception
MsgBox("fail to send data")
End Try
End Sub
[update]
I changed my approach. I just used a Do loop but the result is still not consistent. I chose not to use timer any more but just use ReceiveData Event Handler.
Private Sub DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
Dim ret As Integer
Do
ret = SerialPort.ReadByte()
str &= System.Convert.ToChar(ret)
If ret = 13 Then
ret = SerialPort.ReadByte()
If ret = 10 Then
Exit Do
End If
End If
Loop
Me.Label2.Text = str
str = ""
End Sub
I use Docklight to test my code, you can tell sometimes it sends twice in a row before get the data back. I am not if it has race condition issue involved, thank.
Need a little help here.
I just want to add a Group Item with Item List on it using the QBFC12 but am having a trouble with it. I have tried creating the same method like this with Inventory Assembly and it works well. but this one makes me feel terrible. When the request is processed, it return error telling that there're missing fields on the request. Hope anyone can help me out with this.
Thanks
Here's my code below:
Dim msgSetRequest As IMsgSetRequest
Dim QBSM As New QBSessionManager
Try
With QBSM
.OpenConnection("", "QB Test")
.BeginSession("", ENOpenMode.omDontCare)
End With
Catch ex As Exception
Throw New Exception(ex.Message)
Return False
End Try
msgSetRequest = QBSM.CreateMsgSetRequest("US", 8, 0)
msgSetRequest.Attributes.OnError = ENRqOnError.roeStop
msgSetRequest.ClearRequests()
Dim gAdd As IItemGroupAdd = msgSetRequest.AppendItemGroupAddRq
gAdd.IsActive.SetValue(True)
gAdd.Name.SetValue("Group Name")
gAdd.ItemDesc.SetValue("Group Description")
For Each gListItem As clsInventoryGroupItem In gItem.InventoryGroupItemList
Dim gItemAdd As IItemGroupLine = msgSetRequest.AppendItemGroupAddRq.ItemGroupLineList.Append
gItemAdd.ItemRef.FullName.SetValue(gListItem.ItemRef)
gItemAdd.Quantity.SetValue(gListItem.Quantity)
Next
Dim response As IMsgSetResponse = QBSM.DoRequests(msgSetRequest)
If response.ResponseList.GetAt(0).StatusCode = 0 Then
MessageBox.Show("Success")
else
MessageBox.Show("An Error occurred while inserting Group")
endif
I think the problem is how you are adding your group lines, but haven't tested it yet. Instead of using ItemGroupLineList.Append from the msgSetRequest, you should call it from your IItemGroupAdd object, gAdd. Here's what I came up with, but didn't test it.
Dim msgSetRequest As IMsgSetRequest
Dim QBSM As New QBSessionManager
Try
With QBSM
.OpenConnection("", "QB Test")
.BeginSession("", ENOpenMode.omDontCare)
End With
Catch ex As Exception
Throw New Exception(ex.Message)
Return False
End Try
msgSetRequest = QBSM.CreateMsgSetRequest("US", 8, 0)
msgSetRequest.Attributes.OnError = ENRqOnError.roeStop
msgSetRequest.ClearRequests()
Dim gAdd As IItemGroupAdd = msgSetRequest.AppendItemGroupAddRq
gAdd.IsActive.SetValue(True)
gAdd.Name.SetValue("Group Name")
gAdd.ItemDesc.SetValue("Group Description")
For Each gListItem As clsInventoryGroupItem In gItem.InventoryGroupItemList
Dim gItemAdd As IItemGroupLine = gAdd.ItemGroupLineList.Append
gItemAdd.ItemRef.FullName.SetValue(gListItem.ItemRef)
gItemAdd.Quantity.SetValue(gListItem.Quantity)
Next
Dim response As IMsgSetResponse = QBSM.DoRequests(msgSetRequest)
If response.ResponseList.GetAt(0).StatusCode = 0 Then
MessageBox.Show("Success")
else
MessageBox.Show("An Error occurred while inserting Group")
endif
I am trying to upload a large (4MB+) file to youtube using the API in VB.NET.
Smaller files upload fine, but anything larger than about 4MB gives an error which (I think) is actually related to a timeout: The request was aborted: The request was canceled.
I have read and re-read the API doco, googled, etc looking for an example in VB.NET, but nothing seems to be out there for vb.net
A few coders have hit the same problem and the responses have all been around c# or Java - neither of which I am familiar with.
I tried different combinations of the settings.timeout and settings.maximum, but it does not seem to make a difference
Current code is:
Sub UploadYouTube(ByVal sSourceFile As String, ByVal sTitle As String, ByVal sMediaCategory As String, ByVal sDesc As String)
Dim uSettings As YouTubeRequestSettings, uRequest As YouTubeRequest, newVideo As Video, CreatedVideo As Video, VideoId As String
Dim vContentType As String = "video"
Try
uSettings = New YouTubeRequestSettings(, , , )
uRequest = New YouTubeRequest(uSettings)
newVideo = New Video()
newVideo.Title = sTitle '"Test";
newVideo.Tags.Add(New MediaCategory("Education", YouTubeNameTable.CategorySchema))
newVideo.Description = sDesc '"Testing Testing Testing"
newVideo.YouTubeEntry.Private = False
uRequest.Settings.Timeout = 60 * 60 * 1000
uRequest.Settings.Maximum = 2000000000
' Determine the content type
If sSourceFile.EndsWith(".mov") Then
vContentType = "video/quicktime"
ElseIf sSourceFile.EndsWith(".avi") Or sSourceFile.EndsWith(".mpg") Or sSourceFile.EndsWith(".mpeg") Then
vContentType = "video/mpeg"
ElseIf sSourceFile.EndsWith(".wmv") Then
vContentType = "video/x-ms-wmv"
ElseIf sSourceFile.EndsWith(".m4v") Then
vContentType = "video/m4v"
ElseIf sSourceFile.EndsWith(".mp4") Then
vContentType = "video/mp4"
ElseIf sSourceFile.EndsWith(".3gp") Then
vContentType = "video/3gpp"
End If
newVideo.YouTubeEntry.MediaSource = New MediaFileSource(sSourceFile, vContentType)
CreatedVideo = uRequest.Upload(newVideo)
VideoId = CreatedVideo.VideoId
' Save the video Id to the database!
Catch ex As Exception
debug.print("Error. MainModule.Main. " & ex.Message, 5)
End Try
End Sub
Any help is greatly appreciated
Tony
Python example : https://github.com/Mathieu69/Pitivi_Gargamel/blob/upload_merger/pitivi/uploader.py did that 3 months ago, hope it helps.
I tried to solve the timeout problem by using a backgroundworker. It works, sort of. It doesn't appear to actually be working in the background. I would think the RunWorkerAsync would start, move on to the next command, and postback. Instead it just hangs for a few minutes like it's uploading the whole 75MB file, then posts back successful. If I take away the backgroundworker and just execute the upload however, it fails like yours did. Here's my code that kind of works.
Sub up_load(s As Object, e As EventArgs)
Dim worker As BackgroundWorker = New BackgroundWorker
worker.WorkerReportsProgress = True
worker.WorkerSupportsCancellation = True
AddHandler (worker.DoWork), AddressOf begin_upload
worker.RunWorkerAsync()
lblmsg.Text = "Successfully initiated upload"
End Sub
Sub begin_upload(s As Object, e As DoWorkEventArgs)
Dim request As New YouTubeRequest(settings)
Dim vidupload As New Video()
vidupload.Title = "My Big Test Movie"
vidupload.Tags.Add(New MediaCategory("Nonprofit", YouTubeNameTable.CategorySchema))
vidupload.Keywords = "church, jesus"
vidupload.Description = "See the entire video"
vidupload.YouTubeEntry.Private = False
vidupload.YouTubeEntry.setYouTubeExtension("location", "Downers Grove, IL")
vidupload.YouTubeEntry.MediaSource = New MediaFileSource("c:\users\greg\test3.asf", "video/x-ms-wmv")
Dim createdVideo As Video = Request.Upload(vidupload)
End Sub
I'm trying to get started with Fedex'es Address validation service and I'm running into a road block with FedEx's own demo application.
This is the code in there app:
Sub Main()
''# Build a AddressValidationRequest object
Dim request As AddressValidationRequest = New AddressValidationRequest()
Console.WriteLine("--- Setting Credentials ---")
request.WebAuthenticationDetail = New WebAuthenticationDetail()
request.WebAuthenticationDetail.UserCredential = New WebAuthenticationCredential()
request.WebAuthenticationDetail.UserCredential.Key = "###" ''# Replace "XXX" with the Key
request.WebAuthenticationDetail.UserCredential.Password = "###" ''# Replace "XXX" with the Password
Console.WriteLine("--- Setting Account Information ---")
request.ClientDetail = New ClientDetail()
request.ClientDetail.AccountNumber = "###" ''# Replace "XXX" with clients account number
request.ClientDetail.MeterNumber = "###" ''# Replace "XXX" with clients meter number
request.TransactionDetail = New TransactionDetail()
request.TransactionDetail.CustomerTransactionId = "Address Validation v2 Request using VB.NET Sample Code" ''# This is just an echo back
request.Version = New VersionId()
request.RequestTimestamp = DateTime.Now
Console.WriteLine("--- Setting Validation Options ---")
request.Options = New AddressValidationOptions()
request.Options.CheckResidentialStatus = True
request.Options.MaximumNumberOfMatches = 5
request.Options.StreetAccuracy = AddressValidationAccuracyType.LOOSE
request.Options.DirectionalAccuracy = AddressValidationAccuracyType.LOOSE
request.Options.CompanyNameAccuracy = AddressValidationAccuracyType.LOOSE
request.Options.ConvertToUpperCase = True
request.Options.RecognizeAlternateCityNames = True
request.Options.ReturnParsedElements = True
Console.WriteLine("--- Address 1 ---")
request.AddressesToValidate = New AddressToValidate(1) {New AddressToValidate(), New AddressToValidate()}
request.AddressesToValidate(0).AddressId = "WTC"
request.AddressesToValidate(0).Address = New Address()
request.AddressesToValidate(0).Address.StreetLines = New String(0) {"10 FedEx Parkway"}
request.AddressesToValidate(0).Address.PostalCode = "38017"
request.AddressesToValidate(0).CompanyName = "FedEx Services"
Console.WriteLine("--- Address 2 ---")
request.AddressesToValidate(1).AddressId = "Kinkos"
request.AddressesToValidate(1).Address = New Address()
request.AddressesToValidate(1).Address.StreetLines = New String(0) {"50 N Front St"}
request.AddressesToValidate(1).Address.PostalCode = "38103"
request.AddressesToValidate(1).CompanyName = "FedEx Kinkos"
Dim addressValidationService As AddressValidationService.AddressValidationService = New AddressValidationService.AddressValidationService
''#
Try
''# This is the call to the web service passing in a AddressValidationRequest and returning a AddressValidationReply
Console.WriteLine("--- Sending Request..... ---")
Dim reply As New AddressValidationReply()
reply = addressValidationService.addressValidation(request)
Console.WriteLine("--- Processing request.... ---")
''#This is where I get the error
If (Not reply.HighestSeverity = NotificationSeverityType.ERROR) And (Not reply.HighestSeverity = NotificationSeverityType.FAILURE) Then
If (Not reply.AddressResults Is Nothing) Then
For Each result As AddressValidationResult In reply.AddressResults
Console.WriteLine("Address Id - " + result.AddressId)
Console.WriteLine("--- Proposed Details ---")
If (Not result.ProposedAddressDetails Is Nothing) Then
For Each detail As ProposedAddressDetail In result.ProposedAddressDetails
Console.WriteLine("Score - " + detail.Score)
Console.WriteLine("Address - " + detail.Address.StreetLines(0))
Console.WriteLine(" " + detail.Address.StateOrProvinceCode + " " + detail.Address.PostalCode + " " + detail.Address.CountryCode)
Console.WriteLine("Changes -")
For Each change As AddressValidationChangeType In detail.Changes
Console.WriteLine(change.ToString())
Next
Console.WriteLine("")
Next
End If
Console.WriteLine("")
Next
End If
Else
For Each notification As Notification In reply.Notifications
Console.WriteLine(notification.Message)
Next
End If
Catch e As SoapException
Console.WriteLine(e.Detail.InnerText)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
Console.WriteLine("Press any key to quit !")
Console.ReadKey()
End Sub
It seems to send the request object to the web service, but the"reply" object is returned with "Nothing". I could understand if I wrote the code, but good god... they can't even get their own code to work? Has anyone else seen/fixed this problem?
The app shows some tell-tale signs of having been first written in C# and then converted to VB.Net later. Specifically:
Dim request As AddressValidationRequest = New AddressValidationRequest()
Could be shortened to simply:
Dim request As New AddressValidationRequest()
.
If (Not reply.HighestSeverity = NotificationSeverityType.ERROR) And (Not reply.HighestSeverity = NotificationSeverityType.FAILURE) Then
could be written several ways, but at very least I would expect a pure-VB programmer to know of either AndAlso instead of And or <> instead of Not ... = .... Finally:
Dim reply As New AddressValidationReply()
reply = addressValidationService.addressValidation(request)
creates a new object and promptly discards it.