|
@@ -3,8 +3,6 @@
|
|
|
|
|
|
Namespace ted2go
|
|
Namespace ted2go
|
|
|
|
|
|
-#Import "assets/"
|
|
|
|
-
|
|
|
|
'=MODULE=
|
|
'=MODULE=
|
|
|
|
|
|
'This class is the main class
|
|
'This class is the main class
|
|
@@ -56,12 +54,12 @@ Class IRCServer Extends IRCMessageContainer
|
|
Field serverPort:Int
|
|
Field serverPort:Int
|
|
Field sendBuffer:DataBuffer
|
|
Field sendBuffer:DataBuffer
|
|
Field receiveBuffer:DataBuffer=New DataBuffer(512)
|
|
Field receiveBuffer:DataBuffer=New DataBuffer(512)
|
|
- Field fiberSleep:Float=0.26 'Lower value gets internet messages faster but uses more CPU
|
|
|
|
|
|
+ Field fiberSleep:Float=0.35 'Lower value gets internet messages faster but uses more CPU
|
|
Field updateFiber:Fiber 'Fiber for updating internet mesages
|
|
Field updateFiber:Fiber 'Fiber for updating internet mesages
|
|
Field socket:Socket
|
|
Field socket:Socket
|
|
Field stream:SocketStream
|
|
Field stream:SocketStream
|
|
Field nickname:String
|
|
Field nickname:String
|
|
- Field realname:String="KoreIRC"
|
|
|
|
|
|
+ Field realname:String="KoreIRC 1.0"
|
|
Field messageContainers:=New List<IRCMessageContainer>
|
|
Field messageContainers:=New List<IRCMessageContainer>
|
|
Field skipContainers:=New String[]("chanserv","nickserv","services","*") 'Make sure these are lower case!
|
|
Field skipContainers:=New String[]("chanserv","nickserv","services","*") 'Make sure these are lower case!
|
|
|
|
|
|
@@ -386,10 +384,10 @@ Class IRCServer Extends IRCMessageContainer
|
|
Endif
|
|
Endif
|
|
|
|
|
|
Case "NICK" 'Changing names
|
|
Case "NICK" 'Changing names
|
|
- 'Update local name
|
|
|
|
|
|
+ 'Was local name?
|
|
Local wasSelf:Bool
|
|
Local wasSelf:Bool
|
|
If GetNickname(fromUser)=nickname Then
|
|
If GetNickname(fromUser)=nickname Then
|
|
- wasSelf=true
|
|
|
|
|
|
+ wasSelf=True
|
|
nickname=msg
|
|
nickname=msg
|
|
Endif
|
|
Endif
|
|
|
|
|
|
@@ -399,8 +397,12 @@ Class IRCServer Extends IRCMessageContainer
|
|
If u.name=GetNickname(fromUser) Then
|
|
If u.name=GetNickname(fromUser) Then
|
|
u.name=msg
|
|
u.name=msg
|
|
container.SortUsers()
|
|
container.SortUsers()
|
|
- TriggerOnMessage(msg,fromUser,msg,type,container)
|
|
|
|
- parent.OnUserUpdate(container,Self)
|
|
|
|
|
|
+
|
|
|
|
+ If Not wasSelf Then
|
|
|
|
+ TriggerOnMessage(msg,fromUser,msg,type,container)
|
|
|
|
+ parent.OnUserUpdate(container,Self)
|
|
|
|
+ Endif
|
|
|
|
+
|
|
Exit
|
|
Exit
|
|
Endif
|
|
Endif
|
|
Next
|
|
Next
|
|
@@ -464,11 +466,19 @@ Class IRCServer Extends IRCMessageContainer
|
|
nC.type=type
|
|
nC.type=type
|
|
messageContainers.AddLast(nC)
|
|
messageContainers.AddLast(nC)
|
|
parent.OnNewContainer(nC,Self)
|
|
parent.OnNewContainer(nC,Self)
|
|
|
|
+
|
|
|
|
+ 'Load history for chat rooms
|
|
|
|
+ If nC.name.StartsWith("#") Then nC.LoadHistory()
|
|
|
|
+
|
|
Return nC
|
|
Return nC
|
|
End
|
|
End
|
|
|
|
|
|
'Remove a specific message container
|
|
'Remove a specific message container
|
|
Method RemoveMessageContainer(container:IRCMessageContainer)
|
|
Method RemoveMessageContainer(container:IRCMessageContainer)
|
|
|
|
+
|
|
|
|
+ 'Save history for chat rooms
|
|
|
|
+ If container.name.StartsWith("#") Then container.SaveHistory()
|
|
|
|
+
|
|
messageContainers.Remove(container)
|
|
messageContainers.Remove(container)
|
|
If parent Then parent.OnRemoveContainer(container,Self)
|
|
If parent Then parent.OnRemoveContainer(container,Self)
|
|
End
|
|
End
|
|
@@ -507,6 +517,50 @@ Class IRCMessageContainer
|
|
Field gotUsers:Bool 'Have we gotten users before?
|
|
Field gotUsers:Bool 'Have we gotten users before?
|
|
Field messages:=New List<IRCMessage>
|
|
Field messages:=New List<IRCMessage>
|
|
|
|
|
|
|
|
+ Method LogPath:String()
|
|
|
|
+
|
|
|
|
+ Return AppDir() + "/logs/" + parent.serverAddress + "/" + name + ".txt"
|
|
|
|
+
|
|
|
|
+ End
|
|
|
|
+
|
|
|
|
+ Method LoadHistory()
|
|
|
|
+ Local file:String=LoadString( Self.LogPath() )
|
|
|
|
+ If Not file Then Return
|
|
|
|
+
|
|
|
|
+ Local lines:=file.Split( "~n" )
|
|
|
|
+ Local type:String
|
|
|
|
+ Local time:String
|
|
|
|
+ Local user:String
|
|
|
|
+ Local message:String
|
|
|
|
+
|
|
|
|
+ For Local s:=Eachin lines
|
|
|
|
+ If Not s.Contains( ">" ) Or Not s.Contains( " " ) Or Not s.Contains( ":" ) Then Continue
|
|
|
|
+
|
|
|
|
+ type=s.Split( ">" )[0]
|
|
|
|
+ time=s.Split( ">" )[1].Split( " " )[0]
|
|
|
|
+ user=s.Split( ">" )[1].Split( " " )[1].Split( ":" )[0]
|
|
|
|
+ message=s.Split( type + ">" + time + " " + user + ":" )[1]
|
|
|
|
+
|
|
|
|
+ Self.AddMessage( message, user, Self.name, type.ToUpper() ).time=time
|
|
|
|
+ Next
|
|
|
|
+
|
|
|
|
+ End
|
|
|
|
+
|
|
|
|
+ Method SaveHistory()
|
|
|
|
+ Local log:String
|
|
|
|
+
|
|
|
|
+ For Local m:=Eachin Self.messages
|
|
|
|
+ If m.type<>"PRIVMSG" And m.type<>"QUIT" And m.type<>"PART" And m.type<>"JOIN" And m.type<>"NICK" Then Continue
|
|
|
|
+
|
|
|
|
+ log+=m.type+">"+m.time+" "+m.fromUser+":"+m.text+"~n"
|
|
|
|
+ Next
|
|
|
|
+
|
|
|
|
+ If log.Length>2 Then
|
|
|
|
+ CreateFile( LogPath(), True )
|
|
|
|
+ SaveString( log, LogPath() )
|
|
|
|
+ Endif
|
|
|
|
+ End
|
|
|
|
+
|
|
Method Remove() Virtual
|
|
Method Remove() Virtual
|
|
parent.messageContainers.Remove(Self)
|
|
parent.messageContainers.Remove(Self)
|
|
End
|
|
End
|
|
@@ -520,7 +574,7 @@ Class IRCMessageContainer
|
|
End
|
|
End
|
|
|
|
|
|
'Add a message to this container
|
|
'Add a message to this container
|
|
- Method AddMessage(msg:String,fromUser:String="",toUser:String="",type:String="",hostname:string="")
|
|
|
|
|
|
+ Method AddMessage:IRCMessage(msg:String,fromUser:String="",toUser:String="",type:String="",hostname:string="")
|
|
Local nM:=New IRCMessage
|
|
Local nM:=New IRCMessage
|
|
nM.parent=Self
|
|
nM.parent=Self
|
|
nM.text=msg
|
|
nM.text=msg
|
|
@@ -529,6 +583,7 @@ Class IRCMessageContainer
|
|
nM.type=type
|
|
nM.type=type
|
|
nM.hostname=hostname
|
|
nM.hostname=hostname
|
|
messages.AddLast(nM)
|
|
messages.AddLast(nM)
|
|
|
|
+ Return nM
|
|
End
|
|
End
|
|
|
|
|
|
'Sort the userlist
|
|
'Sort the userlist
|
|
@@ -580,6 +635,75 @@ End
|
|
|
|
|
|
'=IRC VIEW=
|
|
'=IRC VIEW=
|
|
|
|
|
|
|
|
+'Highlighter for IRC history text
|
|
|
|
+Function IrcTextHighlighter:Int( text:String,colors:Byte[],sol:Int,eol:Int,state:Int )
|
|
|
|
+ Local i0:=sol
|
|
|
|
+ Local msgStep:Int
|
|
|
|
+ Local userColor:Int
|
|
|
|
+ Local userStart:Int
|
|
|
|
+ Local userEnd:Int
|
|
|
|
+ Local userDone:Bool
|
|
|
|
+
|
|
|
|
+ While i0<eol
|
|
|
|
+ Local chr:=text[i0]
|
|
|
|
+
|
|
|
|
+ If userDone Then
|
|
|
|
+ colors[i0]=0
|
|
|
|
+ Else
|
|
|
|
+ colors[i0]=1
|
|
|
|
+ Endif
|
|
|
|
+
|
|
|
|
+ 'Reset
|
|
|
|
+ If chr=110 And msgStep=6 Then 'n
|
|
|
|
+ msgStep=0
|
|
|
|
+ userDone=False
|
|
|
|
+ Elseif msgStep=6 And chr<>110
|
|
|
|
+ msgStep=5
|
|
|
|
+ Endif
|
|
|
|
+ If chr=126 And msgStep=5 Then '~
|
|
|
|
+ msgStep=6
|
|
|
|
+ Endif
|
|
|
|
+
|
|
|
|
+ 'Detect username
|
|
|
|
+ If chr=9 And msgStep=2 Then 'Tab
|
|
|
|
+ userStart=i0
|
|
|
|
+ msgStep=3
|
|
|
|
+ userColor=0
|
|
|
|
+ Elseif msgStep=2 And chr<>9 Then
|
|
|
|
+ msgStep=5
|
|
|
|
+ Endif
|
|
|
|
+ If chr=32 And msgStep=4 Then 'Space after :
|
|
|
|
+ userEnd=i0-1
|
|
|
|
+ msgStep=5
|
|
|
|
+ userDone=True
|
|
|
|
+ For Local i1:Int=userStart Until userEnd
|
|
|
|
+ colors[i1]=2 + (userColor Mod 5)
|
|
|
|
+ Next
|
|
|
|
+ Elseif msgStep=4 And chr<>32 Then
|
|
|
|
+ msgStep=5
|
|
|
|
+ Endif
|
|
|
|
+ If chr=58 And msgStep=3 Then ':
|
|
|
|
+ msgStep=4
|
|
|
|
+ Endif
|
|
|
|
+
|
|
|
|
+ If msgStep=3 Then userColor+=chr
|
|
|
|
+
|
|
|
|
+ 'Detect time
|
|
|
|
+ If chr=91 And msgStep=0 Then '[
|
|
|
|
+ msgStep=1
|
|
|
|
+ Endif
|
|
|
|
+ If msgStep=1 Then colors[i0]=1
|
|
|
|
+
|
|
|
|
+ If chr=93 And msgStep=1 Then ']
|
|
|
|
+ msgStep=2
|
|
|
|
+ Endif
|
|
|
|
+
|
|
|
|
+ i0+=1
|
|
|
|
+ Wend
|
|
|
|
+
|
|
|
|
+ Return state
|
|
|
|
+End
|
|
|
|
+
|
|
'This is a pre-made IRC client, ready to be used in any MojoX application
|
|
'This is a pre-made IRC client, ready to be used in any MojoX application
|
|
Class IRCView Extends DockingView
|
|
Class IRCView Extends DockingView
|
|
Field ircHandler:IRC
|
|
Field ircHandler:IRC
|
|
@@ -598,6 +722,8 @@ Class IRCView Extends DockingView
|
|
Field selectedServer:IRCServer
|
|
Field selectedServer:IRCServer
|
|
Field selectedMessageContainer:IRCMessageContainer
|
|
Field selectedMessageContainer:IRCMessageContainer
|
|
|
|
|
|
|
|
+ Field maxHistory:Int=50
|
|
|
|
+
|
|
Property Intro:IRCIntroView()
|
|
Property Intro:IRCIntroView()
|
|
Return introScreen
|
|
Return introScreen
|
|
End
|
|
End
|
|
@@ -615,6 +741,7 @@ Class IRCView Extends DockingView
|
|
|
|
|
|
'Chat history field
|
|
'Chat history field
|
|
historyField=New TextView
|
|
historyField=New TextView
|
|
|
|
+ historyField.Document.TextHighlighter=IrcTextHighlighter
|
|
historyField.ReadOnly=True
|
|
historyField.ReadOnly=True
|
|
historyField.WordWrap=True
|
|
historyField.WordWrap=True
|
|
chatScreen.ContentView=historyField
|
|
chatScreen.ContentView=historyField
|
|
@@ -859,7 +986,7 @@ Class IRCView Extends DockingView
|
|
selectedMessageContainer.AddMessage(selectedServer.nickname+": "+text)
|
|
selectedMessageContainer.AddMessage(selectedServer.nickname+": "+text)
|
|
Else
|
|
Else
|
|
'Yep, add PRIVMSG and send!
|
|
'Yep, add PRIVMSG and send!
|
|
- selectedMessageContainer.AddMessage(selectedServer.nickname+": "+text)
|
|
|
|
|
|
+ selectedMessageContainer.AddMessage( text, selectedServer.nickname, selectedMessageContainer.name, "PRIVMSG" )
|
|
text="PRIVMSG "+selectedMessageContainer.name+" :"+text
|
|
text="PRIVMSG "+selectedMessageContainer.name+" :"+text
|
|
Endif
|
|
Endif
|
|
|
|
|
|
@@ -867,6 +994,23 @@ Class IRCView Extends DockingView
|
|
AddChatMessage(selectedMessageContainer.messages.Last)
|
|
AddChatMessage(selectedMessageContainer.messages.Last)
|
|
End
|
|
End
|
|
|
|
|
|
|
|
+ Method SaveAllHistory()
|
|
|
|
+ For Local s:IRCServer=Eachin Self.ircHandler.servers
|
|
|
|
+ For Local c:IRCMessageContainer=Eachin s.messageContainers
|
|
|
|
+ c.SaveHistory()
|
|
|
|
+ Next
|
|
|
|
+ Next
|
|
|
|
+ End
|
|
|
|
+
|
|
|
|
+ Method Quit(message:String=Null)
|
|
|
|
+ SaveAllHistory()
|
|
|
|
+
|
|
|
|
+ For Local s:IRCServer=Eachin Self.ircHandler.servers
|
|
|
|
+ s.SendString("QUIT :"+message)
|
|
|
|
+ s.Disconnect()
|
|
|
|
+ Next
|
|
|
|
+ End
|
|
|
|
+
|
|
Method OnMessageIRC(message:IRCMessage,container:IRCMessageContainer,server:IRCServer)
|
|
Method OnMessageIRC(message:IRCMessage,container:IRCMessageContainer,server:IRCServer)
|
|
'For message information, visit: https://tools.ietf.org/html/rfc2812
|
|
'For message information, visit: https://tools.ietf.org/html/rfc2812
|
|
Local doNotify:Bool 'Should we notify the user?
|
|
Local doNotify:Bool 'Should we notify the user?
|
|
@@ -877,48 +1021,45 @@ Class IRCView Extends DockingView
|
|
|
|
|
|
Case "JOIN"
|
|
Case "JOIN"
|
|
If message.fromUser=server.nickname Then
|
|
If message.fromUser=server.nickname Then
|
|
|
|
+ UpdateHistory()
|
|
container.AddMessage("You are now talking in "+container.name)
|
|
container.AddMessage("You are now talking in "+container.name)
|
|
Else
|
|
Else
|
|
- container.AddMessage(message.fromUser+" joined "+container.name)
|
|
|
|
|
|
+ container.AddMessage( message.text, message.fromUser, container.name, message.type)
|
|
Endif
|
|
Endif
|
|
|
|
|
|
Case "PART"
|
|
Case "PART"
|
|
- If message.text Then
|
|
|
|
- container.AddMessage(message.fromUser+" left "+container.name+" (reason: "+message.text+")")
|
|
|
|
- Else
|
|
|
|
- container.AddMessage(message.fromUser+" left "+container.name)
|
|
|
|
- Endif
|
|
|
|
|
|
+ container.AddMessage( message.text, message.fromUser, container.name, message.type)
|
|
|
|
|
|
Case "QUIT"
|
|
Case "QUIT"
|
|
- If message.text Then
|
|
|
|
- container.AddMessage(message.fromUser+" quit (reason: "+message.text+")")
|
|
|
|
- Else
|
|
|
|
- container.AddMessage(message.fromUser+" quit")
|
|
|
|
- Endif
|
|
|
|
|
|
+ container.AddMessage( message.text, message.fromUser, container.name, message.type)
|
|
|
|
|
|
Case "NICK"
|
|
Case "NICK"
|
|
- If nicknameLabel.Text.Left(nicknameLabel.Text.Length-1) Then
|
|
|
|
- container.AddMessage("You are now known as "+message.toUser)
|
|
|
|
- Else
|
|
|
|
- container.AddMessage(message.fromUser+" is now known as "+message.toUser)
|
|
|
|
|
|
+ Local wasSelf:Bool
|
|
|
|
+ If container=server And selectedMessageContainer Then
|
|
|
|
+ wasSelf=true
|
|
|
|
+ container=selectedMessageContainer
|
|
Endif
|
|
Endif
|
|
|
|
|
|
|
|
+ container.AddMessage( message.text, message.fromUser, message.toUser, message.type)
|
|
|
|
+
|
|
|
|
+ If wasSelf Then UpdateUsers()
|
|
|
|
+
|
|
Case "PRIVMSG"
|
|
Case "PRIVMSG"
|
|
- container.AddMessage(message.fromUser+": "+message.text)
|
|
|
|
|
|
+ container.AddMessage( message.text, message.fromUser, container.name, message.type)
|
|
doNotify=True
|
|
doNotify=True
|
|
|
|
|
|
Case "NOTICE"
|
|
Case "NOTICE"
|
|
- container.AddMessage("NOTICE >"+message.fromUser+"<: "+message.text)
|
|
|
|
|
|
+ container.AddMessage( message.text, message.fromUser, container.name, message.type)
|
|
|
|
|
|
Default
|
|
Default
|
|
- container.AddMessage(message.fromUser+": "+message.text)
|
|
|
|
|
|
+ container.AddMessage( message.text, message.fromUser, container.name, message.type)
|
|
doNotify=True
|
|
doNotify=True
|
|
End
|
|
End
|
|
|
|
|
|
'Display message if we're in that container right now
|
|
'Display message if we're in that container right now
|
|
If container=selectedMessageContainer Then
|
|
If container=selectedMessageContainer Then
|
|
AddChatMessage(container.messages.Last)
|
|
AddChatMessage(container.messages.Last)
|
|
- Elseif doNotify Then 'Notify user perhaps?
|
|
|
|
|
|
+ Elseif doNotify Then
|
|
Local node:TreeView.Node=GetMessageContainerNode(container.name,server.name)
|
|
Local node:TreeView.Node=GetMessageContainerNode(container.name,server.name)
|
|
If node Then node.Icon=App.Theme.OpenImage("irc/notice.png")
|
|
If node Then node.Icon=App.Theme.OpenImage("irc/notice.png")
|
|
Endif
|
|
Endif
|
|
@@ -1095,14 +1236,68 @@ Class IRCView Extends DockingView
|
|
|
|
|
|
Method UpdateHistory()
|
|
Method UpdateHistory()
|
|
historyField.Clear()
|
|
historyField.Clear()
|
|
|
|
+
|
|
If Not selectedMessageContainer Then Return
|
|
If Not selectedMessageContainer Then Return
|
|
|
|
+
|
|
|
|
+ 'Limit message count
|
|
|
|
+ While selectedMessageContainer.messages.Count()>maxHistory
|
|
|
|
+ selectedMessageContainer.messages.Remove(selectedMessageContainer.messages.First)
|
|
|
|
+ Wend
|
|
|
|
+
|
|
For Local m:=Eachin selectedMessageContainer.messages
|
|
For Local m:=Eachin selectedMessageContainer.messages
|
|
AddChatMessage(m)
|
|
AddChatMessage(m)
|
|
Next
|
|
Next
|
|
End
|
|
End
|
|
|
|
|
|
|
|
+ Function PadTime:String(timeStr:String)
|
|
|
|
+ If Not timeStr.Contains(":") Return timeStr
|
|
|
|
+
|
|
|
|
+ Local t:=timeStr.Split(":")
|
|
|
|
+ If t[0].Length<=1 Then t[0]="0"+t[0]
|
|
|
|
+ If t[1].Length<=1 Then t[1]="0"+t[1]
|
|
|
|
+
|
|
|
|
+ Return t[0]+":"+t[1]
|
|
|
|
+ End
|
|
|
|
+
|
|
Method AddChatMessage(message:IRCMessage)
|
|
Method AddChatMessage(message:IRCMessage)
|
|
- historyField.AppendText("["+message.time+"]~t"+message.text+"~n")
|
|
|
|
|
|
+ Local time:String="["+PadTime(message.time)+"]~t"
|
|
|
|
+
|
|
|
|
+ Select message.type.ToUpper()
|
|
|
|
+
|
|
|
|
+ Case "JOIN"
|
|
|
|
+ historyField.AppendText( time + message.fromUser + " joined " + message.toUser + "~n" )
|
|
|
|
+
|
|
|
|
+ Case "PART"
|
|
|
|
+ If message.text Then
|
|
|
|
+ historyField.AppendText( time + message.fromUser + " left " + message.toUser + " (Reason " + message.text + ")~n" )
|
|
|
|
+ Else
|
|
|
|
+ historyField.AppendText( time + message.fromUser + " left " + message.toUser + "~n" )
|
|
|
|
+ Endif
|
|
|
|
+
|
|
|
|
+ Case "QUIT"
|
|
|
|
+ If message.text Then
|
|
|
|
+ historyField.AppendText( time + message.fromUser + " quit (Reason '" + message.text + "')~n" )
|
|
|
|
+ Else
|
|
|
|
+ historyField.AppendText( time + message.fromUser + " quit~n" )
|
|
|
|
+ Endif
|
|
|
|
+
|
|
|
|
+ Case "NICK"
|
|
|
|
+ historyField.AppendText( time + message.fromUser + " is now known as " + message.text + "~n" )
|
|
|
|
+
|
|
|
|
+ Case "MODE"
|
|
|
|
+ 'historyField.AppendText( time + message.fromUser + " sets MODE " + message.text + "~n" )
|
|
|
|
+
|
|
|
|
+ Case "NOTICE"
|
|
|
|
+ historyField.AppendText( time + message.fromUser + ": <NOTICE> " + message.text + "~n" )
|
|
|
|
+
|
|
|
|
+ Default
|
|
|
|
+ If message.fromUser Then
|
|
|
|
+ historyField.AppendText( time + message.fromUser + ": " + message.text + "~n" )
|
|
|
|
+ Else
|
|
|
|
+ historyField.AppendText( time + message.text + "~n" )
|
|
|
|
+ Endif
|
|
|
|
+ End
|
|
|
|
+
|
|
End
|
|
End
|
|
|
|
|
|
Method OnRender(canvas:Canvas) Override
|
|
Method OnRender(canvas:Canvas) Override
|