-------------------------------------------------
[18/12/2018] - ~4mins - #golang #code
-------------------------------------------------
Contrairement à hier, j'écris l'article au fil de l'eau.
Bon pour ce second jour j'ai commencé par automatiser un poil la façon de tester le code.
Pour le moment je lançais un netcat en écoute sur un port dans un terminal, puis je lançais le go run ircc.go.
Sauf qu'à chaque fois que je le quittais, fallait retourner sur le term avec le netcat et le relancer… **chiant**.
Du coup premier truc de la journée : faire un micro-script shell pour lancer ça dans un tmux :
{{}}
Reload(){
tmux send-keys -t .+ C-c
tmux send-keys C-c
tmux send-keys -t .+ nc Space -l Space -p Space 6667 Enter
tmux send-keys go Space run Space ircc.go Enter
}
Loop(){
while true
do
read -s -n 1 input
Reload
done
}
Loop
{{}}
Il permet d'envoyer un Ctrl-c aux deux panes, puis de relancer le serveur et le programme en Go.
La boucle permet de relancer ces actions en appuyant sur n'importe quelle touche comme ça c'est on ne peut plus simple.
Ouai c'était pas terrible du coup j'ai commencé à mettre tout pleins de variables.
Déjà parceque c'est facile à faire, il suffit d'être méticuleux et de ne rien oublier.
Pour commencer la journée c'est soft.
J'en ai également profité pour tenter de récupérer les arguments donnés au programme.
Pour l'instant j'en ai pas spécialement besoin mais ça pourrait servir ensuite.
Du coup j'en profite pour récupérer os.Args (en testant au préalable sa longueur).
Je pourrai picorer cet exemple plus tard pour l'utiliser différemment.
Bon pour l'instant c'était très très basique.
Du coup je me suis attelé à faire ça un peu plus proprement.
Je suis donc parti dans l'idée de récupérer une chaîne de caractère et de l'éclater en plusieurs sous-chaîne (séparée par des espaces) pour ensuite comparer certains champs seulement.
En fonction de ça je déclenche des actions bidons pour le moment.
J'ai dégainé la RFC d'IRC [1] car ça devenait indispensable sur certains points.
J'entrevois déjà pas mal de limitations dans ma façon de coder.
Je me retrouve à balader certaines variables un peu partout (les conn, nick et compagnie).
J'imagine qu'il y a moyen de faire autrement mais ça va être vite compliqué sinon.
Il me faut donc trouver le moyen de pouvoir écrire une fonction "envoyer_sur_IRC" qui soit appelable d'à peu près partout sans lui donner le socket et compagnie…
{{}}
package main
import (
"bufio"
"fmt"
"net"
"os"
"io"
"strings"
"time"
)
func main() {
var server string = "localhost"
var port string = "6667"
var channel string = "#lms"
var nick string = "bab"
var commander string = ":Lord!Lord@geeknode.fuckyeah"
if len(os.Args) > 1 {
server = os.Args[1]
}
conn, err := net.Dial("tcp",server+":"+port)
go incoming(conn)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer conn.Close()
connbuf := bufio.NewReader(conn)
go io.Copy(conn, os.Stdin)
initIrc(conn, nick, channel)
for {
msg, err := connbuf.ReadString('\n')
if err != nil {
break
}
fmt.Println("<< "+msg)
parseIrc(msg,conn,commander,channel)
}
}
// ------------------
// Côté IRC
// ------------------
func initIrc(conn net.Conn, nick string, channel string){
fmt.Println("NICK "+nick+"\n")
io.WriteString(conn,"NICK "+nick+"\n")
fmt.Println("USER "+nick+"0.0.0.0 "+nick+" :"+nick+" bot\n")
io.WriteString(conn,"USER "+nick+" 0.0.0.0 "+nick+" :"+nick+" bot\n")
fmt.Println("JOIN "+channel+"\n")
io.WriteString(conn,"JOIN "+channel+"\n")
}
func parseIrc(msg string,conn net.Conn, commander string, channel string){
var elements []string = strings.Fields(msg)
for i, element := range elements {
fmt.Println( i,": "+element )
if elements[1] == "421" {
fmt.Println("!! Commande non reconnue par le serveur !!")
break
}
if elements[0] == "PING" {
fmt.Println(">> PONG "+strings.TrimPrefix(msg, "PING :"))
io.WriteString(conn,"PONG "+strings.TrimPrefix(msg, "PING :"))
break
}
if elements[1] == "JOIN" {
fmt.Println("On a rejoin le salon "+strings.Trim(elements[2],":"))
break
}
if elements[1] == "PART" {
fmt.Println("On est parti de "+strings.Trim(elements[2],":"))
break
}
}
}
func sendIrc(conn net.Conn,channel string, msg string){
fmt.Println(">> PRIVMSG "+channel+" :"+msg)
io.WriteString(conn,">> PRIVMSG "+channel+" :"+msg)
}
// ------------------
// Serveur en écoute
// ------------------
func incoming(outconn net.Conn){
ln, err :=net.Listen("tcp",":4321")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
for {
conn, err :=ln.Accept()
if err != nil {
fmt.Println(err)
continue
}
go handleIncoming(conn, outconn)
}
}
func handleIncoming(in net.Conn, out net.Conn){
fmt.Println("Incoming from ",in.RemoteAddr())
inbuf := bufio.NewReader(in)
for {
inmsg, err := inbuf.ReadString('\n')
if err != nil {
break
}
fmt.Println("<<]] "+inmsg)
io.WriteString(out,"PRIVMSG #lms :"+inmsg)
time.Sleep(500 * time.Millisecond)
}
}
{{}}
[1] la RFC d'IRC (https://tools.ietf.org/html/rfc1459)
------------------------------------
------------------------------------
[18/12/2018] - #golang #code
------------------------------------
[>> Suivant >>] ⏭ L'affaire du Siècle
[<< Précédent <<] ⏮ Une semaine pour coder par soi même : Jour 1