mirror of
https://github.com/IllusionMan1212/gorc.git
synced 2026-10-24 02:12:33 +00:00
refactor: change project structure
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License along
|
// You should have received a copy of the GNU General Public License along
|
||||||
// with this program; if not, see https://www.gnu.org/licenses.
|
// with this program; if not, see https://www.gnu.org/licenses.
|
||||||
|
|
||||||
package client
|
package irc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
@@ -307,7 +307,6 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* --- RPL_ISUPPORT Parameters --- */
|
/* --- RPL_ISUPPORT Parameters --- */
|
||||||
|
|
||||||
var Features = map[string]bool{
|
var Features = map[string]bool{
|
||||||
"ACCEPT": true,
|
"ACCEPT": true,
|
||||||
"AWAYLEN": true,
|
"AWAYLEN": true,
|
||||||
@@ -0,0 +1,297 @@
|
|||||||
|
// gorc project
|
||||||
|
// Copyright (C) 2021 IllusionMan1212
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, see https://www.gnu.org/licenses.
|
||||||
|
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/illusionman1212/gorc/irc"
|
||||||
|
"github.com/illusionman1212/gorc/irc/commands"
|
||||||
|
"github.com/illusionman1212/gorc/irc/parser"
|
||||||
|
"github.com/illusionman1212/gorc/ui/mainscreen"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ReadLoop(client *irc.Client) {
|
||||||
|
// 512 bytes as a base + 8192 additional bytes for tags
|
||||||
|
r := bufio.NewReaderSize(client.TcpConn, 8192+512)
|
||||||
|
|
||||||
|
for {
|
||||||
|
msg, err := r.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
if err != io.EOF {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
client.TcpConn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = strings.Replace(msg, "\r\n", "", 1)
|
||||||
|
if ircMessage, valid := parser.ParseIRCMessage(msg); valid {
|
||||||
|
HandleCommand(ircMessage, client)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlePing(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
token := msg.Parameters[0]
|
||||||
|
client.SendCommand(commands.PONG, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlePrivMsg(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
nick := strings.SplitN(msg.Source, "!", 2)[0]
|
||||||
|
channel := msg.Parameters[0]
|
||||||
|
msgContent := msg.Parameters[1]
|
||||||
|
privMsg := fmt.Sprintf("%s: %s", nick, msgContent)
|
||||||
|
|
||||||
|
for i, c := range client.Channels {
|
||||||
|
if c.Name == channel {
|
||||||
|
client.Channels[i].History += privMsg + irc.CRLF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleJoin(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
nick := strings.SplitN(msg.Source, "!", 2)[0]
|
||||||
|
channel := msg.Parameters[0]
|
||||||
|
|
||||||
|
joinMsg := fmt.Sprintf("== %s has joined", nick)
|
||||||
|
for i, c := range client.Channels {
|
||||||
|
if c.Name == channel {
|
||||||
|
client.Channels[i].History += joinMsg + irc.CRLF
|
||||||
|
if _, exists := client.Channels[i].Users[nick]; !exists {
|
||||||
|
client.Channels[i].Users[nick] = irc.User{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if channel == client.ActiveChannel {
|
||||||
|
client.Tea.Send(mainscreen.SwitchChannels())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleQuit(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
nick := strings.SplitN(msg.Source, "!", 2)[0]
|
||||||
|
reason := msg.Parameters[0]
|
||||||
|
quitMsg := fmt.Sprintf("== %s has quit (%s)", nick, reason)
|
||||||
|
|
||||||
|
for i := range client.Channels {
|
||||||
|
// skip the server "channel"
|
||||||
|
if i == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
client.Channels[i].History += quitMsg + irc.CRLF
|
||||||
|
delete(client.Channels[i].Users, nick)
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Tea.Send(mainscreen.SwitchChannels())
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlePart(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
nick := strings.SplitN(msg.Source, "!", 2)[0]
|
||||||
|
channel := msg.Parameters[0]
|
||||||
|
reason := ""
|
||||||
|
if len(msg.Parameters) > 1 {
|
||||||
|
reason = msg.Parameters[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
partMsg := fmt.Sprintf("== %s has left %s (%s)", nick, channel, reason)
|
||||||
|
|
||||||
|
for i, c := range client.Channels {
|
||||||
|
if c.Name == channel {
|
||||||
|
client.Channels[i].History += partMsg + irc.CRLF
|
||||||
|
delete(client.Channels[i].Users, nick)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Tea.Send(mainscreen.SwitchChannels())
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleWELCOME(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
welcomeMsg := msg.Parameters[1]
|
||||||
|
|
||||||
|
client.Channels[0].History += welcomeMsg + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleYOURHOST(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
host := msg.Parameters[1]
|
||||||
|
|
||||||
|
client.Channels[0].History += host + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCREATED(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
created := msg.Parameters[1]
|
||||||
|
|
||||||
|
client.Channels[0].History += created + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleMYINFO(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
info := strings.Join(msg.Parameters[1:], " ")
|
||||||
|
|
||||||
|
client.Channels[0].History += info + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLUSERCLIENT(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
message := msg.Parameters[1]
|
||||||
|
|
||||||
|
client.Channels[0].History += message + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLUSEROP(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
message := strings.Join(msg.Parameters[1:], " ")
|
||||||
|
|
||||||
|
client.Channels[0].History += message + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLUSERUNKNOWN(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
message := strings.Join(msg.Parameters[1:], " ")
|
||||||
|
|
||||||
|
client.Channels[0].History += message + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLUSERCHANNELS(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
message := strings.Join(msg.Parameters[1:], " ")
|
||||||
|
|
||||||
|
client.Channels[0].History += message + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLUSERME(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
message := msg.Parameters[1]
|
||||||
|
|
||||||
|
client.Channels[0].History += message + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLOCALUSERS(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
message := msg.Parameters[1]
|
||||||
|
|
||||||
|
client.Channels[0].History += message + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleGLOBALUSERS(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
message := msg.Parameters[1]
|
||||||
|
|
||||||
|
client.Channels[0].History += message + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleNAMREPLY(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
// TODO: do i need these
|
||||||
|
// client := msg.Parameters[0]
|
||||||
|
// chanSymbol := msg.Parameters[1]
|
||||||
|
channel := msg.Parameters[2]
|
||||||
|
nicks := strings.Split(msg.Parameters[3], " ")
|
||||||
|
|
||||||
|
for i, c := range client.Channels {
|
||||||
|
if c.Name == channel {
|
||||||
|
for _, nick := range nicks {
|
||||||
|
prefix := ""
|
||||||
|
_nick := nick
|
||||||
|
|
||||||
|
if commands.UserPrefixes[string(nick[0])] {
|
||||||
|
prefix = string(nick[0])
|
||||||
|
_nick = nick[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Channels[i].Users[_nick] = irc.User{
|
||||||
|
Prefix: prefix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if channel == client.ActiveChannel {
|
||||||
|
client.Tea.Send(mainscreen.SwitchChannels())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleMOTDStart(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
params := strings.Join(msg.Parameters[1:], " ")
|
||||||
|
|
||||||
|
client.Channels[0].History += params + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleMOTD(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
messageLine := msg.Parameters[1]
|
||||||
|
|
||||||
|
client.Channels[0].History += messageLine + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleCommand(msg parser.IRCMessage, client *irc.Client) {
|
||||||
|
// TODO: handle different commands
|
||||||
|
switch msg.Command {
|
||||||
|
case commands.PING:
|
||||||
|
handlePing(msg, client)
|
||||||
|
case commands.PRIVMSG:
|
||||||
|
handlePrivMsg(msg, client)
|
||||||
|
case commands.JOIN:
|
||||||
|
handleJoin(msg, client)
|
||||||
|
case commands.QUIT:
|
||||||
|
handleQuit(msg, client)
|
||||||
|
case commands.PART:
|
||||||
|
handlePart(msg, client)
|
||||||
|
case commands.RPL_WELCOME:
|
||||||
|
handleWELCOME(msg, client)
|
||||||
|
case commands.RPL_YOURHOST:
|
||||||
|
handleYOURHOST(msg, client)
|
||||||
|
case commands.RPL_CREATED:
|
||||||
|
handleCREATED(msg, client)
|
||||||
|
case commands.RPL_MYINFO:
|
||||||
|
handleMYINFO(msg, client)
|
||||||
|
case commands.RPL_LUSERCLIENT:
|
||||||
|
handleLUSERCLIENT(msg, client)
|
||||||
|
case commands.RPL_LUSEROP:
|
||||||
|
handleLUSEROP(msg, client)
|
||||||
|
case commands.RPL_LUSERUNKNOWN:
|
||||||
|
handleLUSERUNKNOWN(msg, client)
|
||||||
|
case commands.RPL_LUSERCHANNELS:
|
||||||
|
handleLUSERCHANNELS(msg, client)
|
||||||
|
case commands.RPL_LUSERME:
|
||||||
|
handleLUSERME(msg, client)
|
||||||
|
case commands.RPL_LOCALUSERS:
|
||||||
|
handleLOCALUSERS(msg, client)
|
||||||
|
case commands.RPL_GLOBALUSERS:
|
||||||
|
handleGLOBALUSERS(msg, client)
|
||||||
|
case commands.RPL_NAMREPLY:
|
||||||
|
handleNAMREPLY(msg, client)
|
||||||
|
case commands.RPL_ENDOFNAMES:
|
||||||
|
// TODO: toggle a flag on the channel to indicate
|
||||||
|
// it received all the names correctly.
|
||||||
|
|
||||||
|
// start a timeout and update said timeout on every RPL_NAMREPLY
|
||||||
|
// and log an error if timeout ends without receiving this command.
|
||||||
|
case commands.RPL_MOTDSTART:
|
||||||
|
handleMOTDStart(msg, client)
|
||||||
|
case commands.RPL_MOTD:
|
||||||
|
handleMOTD(msg, client)
|
||||||
|
case commands.RPL_ENDOFMOTD:
|
||||||
|
// TODO: toggle a flag on the client/server to indicate
|
||||||
|
// it received all the MOTD correctly
|
||||||
|
|
||||||
|
// start a timeout and update said timeout on every RPL_MOTD
|
||||||
|
// and log an error if timeout ends without receiving this command.
|
||||||
|
default:
|
||||||
|
fullMsg := fmt.Sprintf("%s %s %s %s", msg.Tags, msg.Source, msg.Command, strings.Join(msg.Parameters, " "))
|
||||||
|
|
||||||
|
client.Channels[0].History += fullMsg + irc.CRLF
|
||||||
|
}
|
||||||
|
|
||||||
|
// send a receivedIRCmsg tea message so the ui can update
|
||||||
|
// we also use this tea message to scroll the viewport down
|
||||||
|
client.Tea.Send(mainscreen.ReceivedIRCMsg())
|
||||||
|
}
|
||||||
+6
-11
@@ -17,11 +17,10 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
|
|
||||||
"github.com/charmbracelet/bubbles/textinput"
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/illusionman1212/gorc/client"
|
"github.com/illusionman1212/gorc/irc"
|
||||||
|
"github.com/illusionman1212/gorc/irc/handler"
|
||||||
"github.com/illusionman1212/gorc/ui"
|
"github.com/illusionman1212/gorc/ui"
|
||||||
"github.com/illusionman1212/gorc/ui/login"
|
"github.com/illusionman1212/gorc/ui/login"
|
||||||
"github.com/illusionman1212/gorc/ui/mainscreen"
|
"github.com/illusionman1212/gorc/ui/mainscreen"
|
||||||
@@ -42,10 +41,10 @@ type UI struct {
|
|||||||
|
|
||||||
type State struct {
|
type State struct {
|
||||||
UI UI
|
UI UI
|
||||||
Client *client.Client
|
Client *irc.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func initialUiState(client *client.Client) UI {
|
func initialUiState(client *irc.Client) UI {
|
||||||
return UI{
|
return UI{
|
||||||
Login: login.NewLogin(),
|
Login: login.NewLogin(),
|
||||||
MainScreen: mainscreen.NewMainScreen(client),
|
MainScreen: mainscreen.NewMainScreen(client),
|
||||||
@@ -53,7 +52,7 @@ func initialUiState(client *client.Client) UI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func InitialState() *State {
|
func InitialState() *State {
|
||||||
client := &client.Client{}
|
client := &irc.Client{}
|
||||||
|
|
||||||
return &State{
|
return &State{
|
||||||
Client: client,
|
Client: client,
|
||||||
@@ -97,11 +96,7 @@ func (s State) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
|
|
||||||
mainscreen.LastTabIndexInTabBar = len(s.Client.Channels) - 1
|
mainscreen.LastTabIndexInTabBar = len(s.Client.Channels) - 1
|
||||||
|
|
||||||
// 512 bytes as a base + 8192 additional bytes for tags
|
go handler.ReadLoop(s.Client)
|
||||||
r := bufio.NewReaderSize(s.Client.TcpConn, 8192+512)
|
|
||||||
s.UI.MainScreen.ConnReader = r
|
|
||||||
|
|
||||||
go s.UI.MainScreen.ReadLoop()
|
|
||||||
|
|
||||||
return s, textinput.Blink
|
return s, textinput.Blink
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,32 +17,9 @@
|
|||||||
package mainscreen
|
package mainscreen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/illusionman1212/gorc/parser"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *State) ReadLoop() {
|
|
||||||
for {
|
|
||||||
msg, err := s.ConnReader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
if err != io.EOF {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
s.Client.TcpConn.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = strings.Replace(msg, "\r\n", "", 1)
|
|
||||||
if ircMessage, valid := parser.ParseIRCMessage(msg); valid {
|
|
||||||
s.HandleCommand(ircMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type SendPrivMsg struct {
|
type SendPrivMsg struct {
|
||||||
Msg string
|
Msg string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,272 +0,0 @@
|
|||||||
// gorc project
|
|
||||||
// Copyright (C) 2021 IllusionMan1212
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License along
|
|
||||||
// with this program; if not, see https://www.gnu.org/licenses.
|
|
||||||
|
|
||||||
package mainscreen
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/illusionman1212/gorc/client"
|
|
||||||
"github.com/illusionman1212/gorc/commands"
|
|
||||||
"github.com/illusionman1212/gorc/parser"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *State) handlePing(msg parser.IRCMessage) {
|
|
||||||
token := msg.Parameters[0]
|
|
||||||
s.Client.SendCommand(commands.PONG, token)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handlePrivMsg(msg parser.IRCMessage) {
|
|
||||||
nick := strings.SplitN(msg.Source, "!", 2)[0]
|
|
||||||
channel := msg.Parameters[0]
|
|
||||||
msgContent := msg.Parameters[1]
|
|
||||||
privMsg := fmt.Sprintf("%s: %s", nick, msgContent)
|
|
||||||
|
|
||||||
for i, c := range s.Client.Channels {
|
|
||||||
if c.Name == channel {
|
|
||||||
s.Client.Channels[i].History += privMsg + client.CRLF
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleJoin(msg parser.IRCMessage) {
|
|
||||||
nick := strings.SplitN(msg.Source, "!", 2)[0]
|
|
||||||
channel := msg.Parameters[0]
|
|
||||||
|
|
||||||
joinMsg := fmt.Sprintf("== %s has joined", nick)
|
|
||||||
for i, c := range s.Client.Channels {
|
|
||||||
if c.Name == channel {
|
|
||||||
s.Client.Channels[i].History += joinMsg + client.CRLF
|
|
||||||
if _, exists := s.Client.Channels[i].Users[nick]; !exists {
|
|
||||||
s.Client.Channels[i].Users[nick] = client.User{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if channel == s.Client.ActiveChannel {
|
|
||||||
s.SidePanel.UpdateNicks()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleQuit(msg parser.IRCMessage) {
|
|
||||||
nick := strings.SplitN(msg.Source, "!", 2)[0]
|
|
||||||
reason := msg.Parameters[0]
|
|
||||||
quitMsg := fmt.Sprintf("== %s has quit (%s)", nick, reason)
|
|
||||||
|
|
||||||
for i := range s.Client.Channels {
|
|
||||||
// skip the server "channel"
|
|
||||||
if i == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
s.Client.Channels[i].History += quitMsg + client.CRLF
|
|
||||||
delete(s.Client.Channels[i].Users, nick)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.SidePanel.UpdateNicks()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handlePart(msg parser.IRCMessage) {
|
|
||||||
nick := strings.SplitN(msg.Source, "!", 2)[0]
|
|
||||||
channel := msg.Parameters[0]
|
|
||||||
reason := ""
|
|
||||||
if len(msg.Parameters) > 1 {
|
|
||||||
reason = msg.Parameters[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
partMsg := fmt.Sprintf("== %s has left %s (%s)", nick, channel, reason)
|
|
||||||
|
|
||||||
for i, c := range s.Client.Channels {
|
|
||||||
if c.Name == channel {
|
|
||||||
s.Client.Channels[i].History += partMsg + client.CRLF
|
|
||||||
delete(s.Client.Channels[i].Users, nick)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.SidePanel.UpdateNicks()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleWELCOME(msg parser.IRCMessage) {
|
|
||||||
welcomeMsg := msg.Parameters[1]
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += welcomeMsg + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleYOURHOST(msg parser.IRCMessage) {
|
|
||||||
host := msg.Parameters[1]
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += host + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleCREATED(msg parser.IRCMessage) {
|
|
||||||
created := msg.Parameters[1]
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += created + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleMYINFO(msg parser.IRCMessage) {
|
|
||||||
info := strings.Join(msg.Parameters[1:], " ")
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += info + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleLUSERCLIENT(msg parser.IRCMessage) {
|
|
||||||
message := msg.Parameters[1]
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += message + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleLUSEROP(msg parser.IRCMessage) {
|
|
||||||
message := strings.Join(msg.Parameters[1:], " ")
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += message + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleLUSERUNKNOWN(msg parser.IRCMessage) {
|
|
||||||
message := strings.Join(msg.Parameters[1:], " ")
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += message + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleLUSERCHANNELS(msg parser.IRCMessage) {
|
|
||||||
message := strings.Join(msg.Parameters[1:], " ")
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += message + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleLUSERME(msg parser.IRCMessage) {
|
|
||||||
message := msg.Parameters[1]
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += message + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleLOCALUSERS(msg parser.IRCMessage) {
|
|
||||||
message := msg.Parameters[1]
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += message + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleGLOBALUSERS(msg parser.IRCMessage) {
|
|
||||||
message := msg.Parameters[1]
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += message + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleNAMREPLY(msg parser.IRCMessage) {
|
|
||||||
// TODO: do i need these
|
|
||||||
// client := msg.Parameters[0]
|
|
||||||
// chanSymbol := msg.Parameters[1]
|
|
||||||
channel := msg.Parameters[2]
|
|
||||||
nicks := strings.Split(msg.Parameters[3], " ")
|
|
||||||
|
|
||||||
for i, c := range s.Client.Channels {
|
|
||||||
if c.Name == channel {
|
|
||||||
for _, nick := range nicks {
|
|
||||||
prefix := ""
|
|
||||||
_nick := nick
|
|
||||||
|
|
||||||
if commands.UserPrefixes[string(nick[0])] {
|
|
||||||
prefix = string(nick[0])
|
|
||||||
_nick = nick[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Client.Channels[i].Users[_nick] = client.User{
|
|
||||||
Prefix: prefix,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if channel == s.Client.ActiveChannel {
|
|
||||||
s.SidePanel.UpdateNicks()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleMOTDStart(msg parser.IRCMessage) {
|
|
||||||
params := strings.Join(msg.Parameters[1:], " ")
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += params + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) handleMOTD(msg parser.IRCMessage) {
|
|
||||||
messageLine := msg.Parameters[1]
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += messageLine + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *State) HandleCommand(msg parser.IRCMessage) {
|
|
||||||
// TODO: handle different commands
|
|
||||||
switch msg.Command {
|
|
||||||
case commands.PING:
|
|
||||||
s.handlePing(msg)
|
|
||||||
case commands.PRIVMSG:
|
|
||||||
s.handlePrivMsg(msg)
|
|
||||||
case commands.JOIN:
|
|
||||||
s.handleJoin(msg)
|
|
||||||
case commands.QUIT:
|
|
||||||
s.handleQuit(msg)
|
|
||||||
case commands.PART:
|
|
||||||
s.handlePart(msg)
|
|
||||||
case commands.RPL_WELCOME:
|
|
||||||
s.handleWELCOME(msg)
|
|
||||||
case commands.RPL_YOURHOST:
|
|
||||||
s.handleYOURHOST(msg)
|
|
||||||
case commands.RPL_CREATED:
|
|
||||||
s.handleCREATED(msg)
|
|
||||||
case commands.RPL_MYINFO:
|
|
||||||
s.handleMYINFO(msg)
|
|
||||||
case commands.RPL_LUSERCLIENT:
|
|
||||||
s.handleLUSERCLIENT(msg)
|
|
||||||
case commands.RPL_LUSEROP:
|
|
||||||
s.handleLUSEROP(msg)
|
|
||||||
case commands.RPL_LUSERUNKNOWN:
|
|
||||||
s.handleLUSERUNKNOWN(msg)
|
|
||||||
case commands.RPL_LUSERCHANNELS:
|
|
||||||
s.handleLUSERCHANNELS(msg)
|
|
||||||
case commands.RPL_LUSERME:
|
|
||||||
s.handleLUSERME(msg)
|
|
||||||
case commands.RPL_LOCALUSERS:
|
|
||||||
s.handleLOCALUSERS(msg)
|
|
||||||
case commands.RPL_GLOBALUSERS:
|
|
||||||
s.handleGLOBALUSERS(msg)
|
|
||||||
case commands.RPL_NAMREPLY:
|
|
||||||
s.handleNAMREPLY(msg)
|
|
||||||
case commands.RPL_ENDOFNAMES:
|
|
||||||
// TODO: toggle a flag on the channel to indicate
|
|
||||||
// it received all the names correctly.
|
|
||||||
|
|
||||||
// start a timeout and update said timeout on every RPL_NAMREPLY
|
|
||||||
// and log an error if timeout ends without receiving this command.
|
|
||||||
case commands.RPL_MOTDSTART:
|
|
||||||
s.handleMOTDStart(msg)
|
|
||||||
case commands.RPL_MOTD:
|
|
||||||
s.handleMOTD(msg)
|
|
||||||
case commands.RPL_ENDOFMOTD:
|
|
||||||
// TODO: toggle a flag on the client/server to indicate
|
|
||||||
// it received all the MOTD correctly
|
|
||||||
|
|
||||||
// start a timeout and update said timeout on every RPL_MOTD
|
|
||||||
// and log an error if timeout ends without receiving this command.
|
|
||||||
default:
|
|
||||||
fullMsg := fmt.Sprintf("%s %s %s %s", msg.Tags, msg.Source, msg.Command, strings.Join(msg.Parameters, " "))
|
|
||||||
|
|
||||||
s.Client.Channels[0].History += fullMsg + client.CRLF
|
|
||||||
}
|
|
||||||
|
|
||||||
// send a receivedIRCmsg tea message so the ui can update
|
|
||||||
// we also use this tea message to scroll the viewport down
|
|
||||||
s.Client.Tea.Send(ReceivedIRCMsg())
|
|
||||||
}
|
|
||||||
@@ -20,13 +20,11 @@ import (
|
|||||||
"github.com/charmbracelet/bubbles/textinput"
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
"github.com/illusionman1212/gorc/client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type InputState struct {
|
type InputState struct {
|
||||||
Input textinput.Model
|
Input textinput.Model
|
||||||
Style lipgloss.Style
|
Style lipgloss.Style
|
||||||
Client *client.Client
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInputBox() InputState {
|
func NewInputBox() InputState {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package mainscreen
|
package mainscreen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -25,8 +24,8 @@ import (
|
|||||||
"github.com/charmbracelet/bubbles/viewport"
|
"github.com/charmbracelet/bubbles/viewport"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
"github.com/illusionman1212/gorc/client"
|
"github.com/illusionman1212/gorc/irc"
|
||||||
"github.com/illusionman1212/gorc/commands"
|
"github.com/illusionman1212/gorc/irc/commands"
|
||||||
"github.com/illusionman1212/gorc/ui"
|
"github.com/illusionman1212/gorc/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -49,8 +48,7 @@ var FirstTabIndexInTabBar = 0
|
|||||||
var LastTabIndexInTabBar = 0
|
var LastTabIndexInTabBar = 0
|
||||||
|
|
||||||
type State struct {
|
type State struct {
|
||||||
ConnReader *bufio.Reader
|
Client *irc.Client
|
||||||
Client *client.Client
|
|
||||||
Viewport *viewport.Model
|
Viewport *viewport.Model
|
||||||
FocusIndex Window
|
FocusIndex Window
|
||||||
TabRenderingDirection TabDirection
|
TabRenderingDirection TabDirection
|
||||||
@@ -59,13 +57,12 @@ type State struct {
|
|||||||
SidePanel *SidePanelState
|
SidePanel *SidePanelState
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMainScreen(client *client.Client) State {
|
func NewMainScreen(client *irc.Client) State {
|
||||||
newViewport := viewport.New(0, 0)
|
newViewport := viewport.New(0, 0)
|
||||||
newViewport.Wrap = viewport.Wrap
|
newViewport.Wrap = viewport.Wrap
|
||||||
newViewport.Style = MessagesStyle.Copy()
|
newViewport.Style = MessagesStyle.Copy()
|
||||||
|
|
||||||
return State{
|
return State{
|
||||||
ConnReader: nil,
|
|
||||||
Client: client,
|
Client: client,
|
||||||
Viewport: &newViewport,
|
Viewport: &newViewport,
|
||||||
FocusIndex: InputBox,
|
FocusIndex: InputBox,
|
||||||
@@ -108,9 +105,9 @@ func (s State) Update(msg tea.Msg) (State, tea.Cmd) {
|
|||||||
s.Client.ActiveChannelIndex = i
|
s.Client.ActiveChannelIndex = i
|
||||||
break
|
break
|
||||||
} else if i == len(s.Client.Channels)-1 {
|
} else if i == len(s.Client.Channels)-1 {
|
||||||
s.Client.Channels = append(s.Client.Channels, client.Channel{
|
s.Client.Channels = append(s.Client.Channels, irc.Channel{
|
||||||
Name: channel,
|
Name: channel,
|
||||||
Users: make(map[string]client.User),
|
Users: make(map[string]irc.User),
|
||||||
})
|
})
|
||||||
s.Client.ActiveChannelIndex = len(s.Client.Channels) - 1
|
s.Client.ActiveChannelIndex = len(s.Client.Channels) - 1
|
||||||
LastTabIndexInTabBar = len(s.Client.Channels) - 1
|
LastTabIndexInTabBar = len(s.Client.Channels) - 1
|
||||||
@@ -124,7 +121,7 @@ func (s State) Update(msg tea.Msg) (State, tea.Cmd) {
|
|||||||
} else {
|
} else {
|
||||||
if s.Client.ActiveChannel != s.Client.Host {
|
if s.Client.ActiveChannel != s.Client.Host {
|
||||||
fullMsg := s.Client.Nickname + ": " + msg.Msg
|
fullMsg := s.Client.Nickname + ": " + msg.Msg
|
||||||
s.Client.Channels[s.Client.ActiveChannelIndex].History += fullMsg + client.CRLF
|
s.Client.Channels[s.Client.ActiveChannelIndex].History += fullMsg + irc.CRLF
|
||||||
// TODO: make sure to only append the message to the history if server sends back no errors
|
// TODO: make sure to only append the message to the history if server sends back no errors
|
||||||
s.Client.SendCommand(commands.PRIVMSG, s.Client.ActiveChannel, msg.Msg)
|
s.Client.SendCommand(commands.PRIVMSG, s.Client.ActiveChannel, msg.Msg)
|
||||||
s.Viewport.SetContent(s.Client.Channels[s.Client.ActiveChannelIndex].History)
|
s.Viewport.SetContent(s.Client.Channels[s.Client.ActiveChannelIndex].History)
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ import (
|
|||||||
"github.com/charmbracelet/bubbles/viewport"
|
"github.com/charmbracelet/bubbles/viewport"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
"github.com/illusionman1212/gorc/client"
|
"github.com/illusionman1212/gorc/irc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SidePanelState struct {
|
type SidePanelState struct {
|
||||||
Client *client.Client
|
Client *irc.Client
|
||||||
Viewport viewport.Model
|
Viewport viewport.Model
|
||||||
Focused bool
|
Focused bool
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ func (s *SidePanelState) getLatestNicks() []string {
|
|||||||
return nicks
|
return nicks
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSidePanel(client *client.Client) *SidePanelState {
|
func NewSidePanel(client *irc.Client) *SidePanelState {
|
||||||
newViewport := viewport.New(0, 0)
|
newViewport := viewport.New(0, 0)
|
||||||
newViewport.Style = SidePanelStyle.Copy()
|
newViewport.Style = SidePanelStyle.Copy()
|
||||||
newViewport.Wrap = viewport.Wrap
|
newViewport.Wrap = viewport.Wrap
|
||||||
|
|||||||
Reference in New Issue
Block a user