Alla fyndtips från mellandagsrean

[Tävling] Skapa en simpel IRC-bot i valfritt språk

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av ErikHK
Ok, här kommer en tråkig bot helt utan features, får se om jag orkar fixa till det, ajja, här är den iallafall, i favoritspråket python :):

#! /usr/bin/env python # -*- coding: iso-8859-1 -*- import sys,os,re,socket host = 'irc.freenode.net' port = 6667 nick = '' chan = '' user = '' realname = '' socket = socket.socket() socket.connect((host, port)) socket.send("NICK %s\r\n" % nick) socket.send("USER %s %s bla :%s\r\n" % (user,host,realname)) socket.send("JOIN %s\r\n" % chan) while 1: line=socket.recv(500) print line

Det mesta säger sig självt, så jag utelämnar kommentarer.

Trevligt. Bara att fill in the blanks.

Vad måste man göra för att ansluta till QuakeNet? Fick typ "you must register user". Är det det där tjafset med att ansluta och skicka massa saker till qnet? :/

Visa signatur

Min hemsida: http://www.srekel.net
Pocket Task Force: http://ptf.srekel.net
Kaka e gott! http://kaka.srekel.net

Permalänk
Medlem

Allt du behöver göra är att behandla det PING-meddelande som dom skickar ut, gick alldeles utmärkt att göra så här för mig (pseudo-kod):

send_command(NICK nickname) send_command(USER nickname foo bar :nickname) stuff = recv_command() if stuff.command == "PING" then send_command(PONG :stuff.message) endif

Permalänk
Medlem

Det är bra med tävligar lite då och då, för då får man förslag på vad man kan göra och man lär sig något nytt. Det var enklare, och roligare, än jag trodde att göra en IRC-bot. Har några saker jag vill fixa/snygga till innan jag kommer med min variant (C++).

Visa signatur

"Sleep is one of those funny things about being a human being" - Marshall Brain
"Mike broke the hubble, Mike broke the hubble" - Mystery Science Theater 3000
"Det finns inget som kan kallas skrot!" säger Mulle Meck, "bara gamla saker som går att använda på nya sätt. Rulla ut och rulla på."

Permalänk
Medlem

Hm, tror inte det riktigt passar in här, men jag har byggt en IRC-service som håller koll på alla användare på hela nätverket, samt ger dem deras rätta modes i kanaler.

Och den klassas knappast till liten och smidig

Visa signatur

+++++++[>++++++++++>+++++++++++++++<<-]>-.---------[>>++<<-]>>----.<-.---.>++++.

Permalänk
Medlem

Här kommer mitt halvtaskiga försök i Python (första jag någonsin skriver i Python), jag hoppas att du inte har någonting emot att jag lånade din trevliga regexp där mOREc. Den skar ner på arbetet något enormt kan jag säga.

Jag brydde mig inte om en regexp för att läsa ur nicket ur prefixet, eftersom det är lätthämtat genom att veta bokstävernas positioner.

Just nu gör den egentligen ingenting utom att ansluta till ett visst nätverk på en viss port, med ett visst nickname och joina en viss/vissa kanal/er.

Man kan invita den till en kanal om man vill, och om man är cool som jag så kan man få den att byta nick, säga saker eller stänga av sig själv.

Möjligheterna finns för att enkelt lägga till s.k triggers (.msg eller !msg eller vad man nu vill använda) som botten kan svara på. Jag funderar på att göra ett lite mer robust säkerhetssystem så att inte vem som helst kan kicka den av nätverket osv.

Rätt nöjd faktiskt, första gången jag skriver någonting i Python och första gången jag gör någonting IRC-relaterat

import sys import socket import re recv_size = 512 # OptionParser makes it easier to use Unix-style command-line # arguments, and as an added bonus it handles the default # values for us so we don't have to muck around setting those up. from optparse import OptionParser parser = OptionParser() parser.add_option("-s", "--servername", dest = "hostname", help = "connect to HOSTNAME", metavar = "HOSTNAME", default = "irc.quakenet.org") parser.add_option("-p","--port", dest = "port", help = "connect on PORT", metavar = "PORT", default = "6668") parser.add_option("-n", "--nickname", dest = "nickname", help = "connect using NICK", metavar = "NICK", default = "filobot") parser.add_option("-c", "--channels", dest = "channels", help = "join CHANNELS. (comma-separated list. No #!)", metavar = "CHANNELS", default = "filotest") parser.add_option("-m","--masters", dest = "masters", help = "empower MASTERS. (comma-separated list of nicks.)", metavar = "MASTERS", default = "kungtotte") (o, args) = parser.parse_args() def send_cmd(sock, str): sock.send(str + "\r\n") def send_msg(sock, target, msg): send_cmd(sock, "PRIVMSG %s :%s" % (target, msg)) def extract_nick(pre): start = 1 # 1 is the first char of the nick. end = pre.find("!") return pre[start:end] def parse_message(d): # Credits to mOREc for this regexp. Pretty damn nifty! p = r'^(:([^ ]+))?[ ]*([^ ]+)[ ]+:?([^ ]*)[ ]*:?(.*)$' r = re.search(p, d, re.M) if r: prefix = r.group(1) command = r.group(3) arg = r.group(4) args = r.group(5) return (prefix, command, arg, args) else: return ("","","","") def handle_private_message(nick, args): words = args.split() masters = o.masters.split() if nick in masters: if words[0] == "nick": send_cmd(s, "NICK %s" % words[1]) o.nickname = words[1] elif words[0] == "addmaster": send_msg(s, nick, "Added %s to list" % words[1]) o.masters = o.masters + "," + words[1] elif words[0] == "quit": s.close() sys.exit(1) elif words[0] == "say": send_msg(s, words[1], ' '.join(words[2:])) def handle_public_message(nick, chan, args): # Left here if we want to put in triggers return try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((o.hostname, int(o.port))) except socket.error, (value,message): if s: s.close() print "Could not connect to IRC server: " + message sys.exit(1) # Register with the server. This works fine on QuakeNet, and I assume # other networks too. send_cmd(s, "NICK " + o.nickname) send_cmd(s, "USER %s foo bar :%s" % (o.nickname, o.nickname)) while True: d = s.recv(recv_size) (prefix, cmd, arg, args) = parse_message(d) if prefix: nick = extract_nick(prefix) # On quakenet this shows are are connected. # I have NO idea how other standards compliant networks handle # this. Need to investigate. if cmd == "001": channels = o.channels.split(',') for c in channels: send_cmd(s, "JOIN #%s" % c) if cmd == "PING": send_cmd(s, "PONG :%s" % arg) elif cmd == "INVITE": chan = args.split()[0] send_cmd(s, "JOIN %s" % chan) elif cmd == "PRIVMSG": if arg == o.nickname: handle_private_message(nick, args) else: handle_public_message(nick, arg, args)

Permalänk

Kul tävling Ska se om jag hinner hacka ihop något i Perl.

Visa signatur

"to conquer others is to have power, to conquer yourself is to know the way"

Permalänk
Medlem

Det bidde ingen irc-bot för mig, det bidde en IRC-klient-java-applet

Borde komma online ikväll om jag orkar fixa lite småbuggar/features

Permalänk
Hedersmedlem

Helt otroligt, jag måste vara blind både igår och tidigare idag har jag kollat på koden som m0REc skrev och var båda gångerna säker på att det var python ocaml.
Först nu såg jag att det var perl och inte python (och nej jag är inte så erfaren pythonprogrammerare så jag såg något direkt fel då jag aldrig kodat i perl heller). Trist.
Anyway några andra botar i python har ju kommit. Jag kan nog inte med IRC-protokollet (får väl läsa in sig på det) så jag rippar nog lite av era bottar
Måste försöka göra något roligt i ocaml också, jag gillar ju funktionella språk, gjort en del i SML men också petat på ocaml. Ska bli roligt

Visa signatur

Forumregler | Feedbackforumet | Något som behöver modereras? Tryck på Anmäl inlägget och ge en anledning, någon moderator kommer granska inlägget och göra (egen) bedömning
"Fate. Protects fools, little children and ships named Enterprise." - Riker - ST:TNG

Permalänk
Hedersmedlem

Kodar jag så snygg Perl?

IRC-protokollet är ganska lätt, en RFC kan hittas här: http://www.irchelp.org/irchelp/rfc/rfc.html

Dessutom gör det där regexpet allting så mycket lättare.

Visa signatur

Vim
Kinesis Classic Contoured (svart), Svorak (A5)
Medlem i signaturgruppen Vimzealoter.

Permalänk
Medlem

Det där regexpet är ju en life-saver. Räddar en från alla hemskheter

Permalänk
Hedersmedlem

Skulle väntat med att publicera det, det hjälper ju bara mina konkurrenter!

Visa signatur

Vim
Kinesis Classic Contoured (svart), Svorak (A5)
Medlem i signaturgruppen Vimzealoter.

Permalänk
Medlem

Min bott är kodad i php och finns just nu i #fuskbugg på qnet.

just nu ca 600 rader kod som jag inte har lust att pasta
har fint stöd för nya funktioner man lägger i en mapp så körs dom med i botten etc.

[EDIT]:
Den heter "pasen"
Och svarar på dessa kommandon just nu (av er);
!netinfo - Visar nätverkstrafik genom min linuxburk
!skurt - Kollar om en speciell använare är inloggad, om så är fallet så ber den om tillåtelse att köra "slay användaren" (Både Yes & No ger tillåtelse ;O)
!radio
!uptime
{highlightningar}
internet
---
Jag kan även ge den order om att säga ngt jag vill att den ska säga osv, och sen har jag som admin övriga rättigheter.

Den har även en funktion som "simulerar" en människa.
Dvs. en sleepfunktion, så att den skriver meningar med ca 7 tecken/sec (är jsut nu min medelhastighet) men denna har jag inaktiverat just nu

[EDIT2++]: för många stavfel

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av m0REc
Kodar jag så snygg Perl?

IRC-protokollet är ganska lätt, en RFC kan hittas här: http://www.irchelp.org/irchelp/rfc/rfc.html

Dessutom gör det där regexpet allting så mycket lättare.

Har kört din oCaml-kod och KTottEs pythonkod för att lära mig.
Men en fråga om protokollet. Som jag förstår RFC:n, stycke 3.3.2 så ska man kunna skicka kommando att en viss text skickas ut i en kanal (iaf om det är 3 eller fler där).
Jag ser inget kommando för att skicka ett meddelande (vanlig chat alltså) till en kanal. Kan väl inte vara så dumt att man måste bråka och fixa in en lista på alla användare i kanalen först och sedan PRIVATMSG till alla?
Jag vill ju att min (nåja, inte "min" ännu) ska kunna chatta lite i kanalen.

Visa signatur

Forumregler | Feedbackforumet | Något som behöver modereras? Tryck på Anmäl inlägget och ge en anledning, någon moderator kommer granska inlägget och göra (egen) bedömning
"Fate. Protects fools, little children and ships named Enterprise." - Riker - ST:TNG

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Aqualize
Har kört din oCaml-kod och KTottEs pythonkod för att lära mig.
Men en fråga om protokollet. Som jag förstår RFC:n, stycke 3.3.2 så ska man kunna skicka kommando att en viss text skickas ut i en kanal (iaf om det är 3 eller fler där).
Jag ser inget kommando för att skicka ett meddelande (vanlig chat alltså) till en kanal. Kan väl inte vara så dumt att man måste bråka och fixa in en lista på alla användare i kanalen först och sedan PRIVATMSG till alla?
Jag vill ju att min (nåja, inte "min" ännu) ska kunna chatta lite i kanalen.

Man kan skicka ett PRIVMSG till en kanal, t.ex:

PRIVMSG #sweclockers :Jag skickar ett meddelande till #sweclockers!

[edit] Detta nämns för övrigt i sektion 3.3.1

Permalänk
Hedersmedlem

Yes, det är PRIVMSG som används. Och ja, det är rejält fult.

Visa signatur

Vim
Kinesis Classic Contoured (svart), Svorak (A5)
Medlem i signaturgruppen Vimzealoter.

Permalänk

Har skrivit en bot jag kallar Iraqi Information Minister (Idén fick jag långt innan detta) idag och den ligger just nu på 400 rader C++kod (något jag inte är inställd på att pasta), återfinnes om än sporadiskt i #deluxesupreme2.0...
- Commands är låsta till en kanal.
- Adminlista är gjord och kan underhållas utan att behöva krångla med omstarter.
- Boten sprutar ur sig en quote om man säger en viss fras i kanalen eller direkt till den. Citaten är tagna från http://www.welovetheiraqiinformationminister.com/ och även en stor del av resten av botens output är i samma anda.

Tyvärr har jag inte gjort någon vidare sträng-dissekerare än, alla commands sköts lite osäkert just nu, begränsningarna är inte många vad gäller placering av nyckelord.

Visa signatur

"90% av att vara smart är att veta sina begränsningar. De återstående 10 procenten är att veta att man måste gå utanför dessa begränsningar."
Hjälp till att öka kunskapen.
FirefoxMyths

Permalänk
Hedersmedlem

Så, då hade man en enkel bot i C också.

Fungerar dock mindre bra (när det gäller splitting av protokollet) när det gäller vissa saker men den fungerar. Skrev den igår typ kl. 4 på morgonen, orkar inte snygga till den samt att jag är sjuk (förkylning, håller på att utveckla en feber =/). Hoppas att den hjälper någon dock.

#include <stdio.h> #include <errno.h> #include <netdb.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #define SERVER "irc.freenode.org" #define PORT 6667 #define CHANNEL "#bot_test" #define NICKNAME "easy_cbot" #define USERNAME "easy_c_bot" #define REALNAME "Easy C IRC-bot" #define BUFSIZE 512 int send_command(int sock, char *data) { int status; sprintf(data, "%s\r\n", data); status = send(sock, data, strlen(data), 0); if (status == -1) { perror("send"); exit(1); } return status; } char *get_nickname(char *string) { int position; char tmp[15]; ++string; for (position = 0; string[position] != '!'; position++); return strncpy(tmp, string, position); } char *get_message(char *string) { return ++string; } int main(int argc, char *argv[]) { int sockfd, numbytes; char buf[BUFSIZE], data[BUFSIZE], *prefix, *command, *arg, *args; struct hostent *he; struct sockaddr_in addr; prefix = NULL; command = NULL; arg = NULL; args = NULL; he = gethostbyname(SERVER); sockfd = socket(PF_INET, SOCK_STREAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr = *((struct in_addr *)he->h_addr); memset(&(addr.sin_zero), '\0', 8); connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)); sprintf(data, "NICK %s", NICKNAME); send_command(sockfd, data); sprintf(data, "USER %s aoeu htns :%s", USERNAME, REALNAME); send_command(sockfd, data); while (1) { numbytes = recv(sockfd, buf, BUFSIZE - 1, 0); buf[numbytes] = '\0'; if (strstr(buf, "004")) { if (strstr(buf, "433")) { printf("Nickname already taken.\n"); exit(1); } else break; } } sprintf(data, "JOIN %s", CHANNEL); send_command(sockfd, data); while (1) { prefix = NULL; command = NULL; arg = NULL; args = NULL; numbytes = recv(sockfd, buf, BUFSIZE - 1, 0) buf[numbytes] = '\0'; prefix = strtok(buf, " "); command = strtok(NULL, " "); arg = strtok(NULL, " "); args = strtok(NULL, ""); if (command != NULL && !strcmp(command, "PRIVMSG")) printf("[MSG] %s> %s", get_nickname(prefix), get_message(args)); else if (command != NULL && !strcmp(command, "NOTICE")) printf("[NOTICE] %s> %s", get_nickname(prefix), get_message(args)); else if (command != NULL && !strcmp(command, "JOIN")) printf("[JOIN] %s -> %s", get_nickname(prefix), get_message(arg)); else if (prefix != NULL && !strcmp(prefix, "PING")) { sprintf(data, "PONG %s", command); send_command(sockfd, data); printf("PING? PONG!\n"); } else printf("[%s] %s {%s} (%s)\n", command, prefix, arg, args); } close(sockfd); return 0; }

EDIT: Notera att det här är för *NIX-system, det är en del ändringar som måste göras för att använda sockets i Windows.

Visa signatur

Vim
Kinesis Classic Contoured (svart), Svorak (A5)
Medlem i signaturgruppen Vimzealoter.

Permalänk
Medlem

En class i PHP5 för en irc-bot..

Sneglade lite på phpsidan.nu (var/är helt ny med irc)..

<?php class ircBot { protected $socket; public $server; public $port; public $password; public $nickname; public $username; public $login_type; public $real_name; public $channel; function start_bot() { $this -> socket = fsockopen($this -> server, $this -> port); if(!$this -> socket) { Die('Kunde inte ansluta'); } else { if(strlen($this -> password) > 0) { $this -> send_data('PASS ' . $this -> password); } $this -> send_data('NICK ' . $this -> nickname); $this -> send_data('USER ' . $this -> username . ' ' . $this -> login_type . ' :' . $this -> real_name); $this -> send_data('JOIN ' . $this -> channel); while($this -> socket) { echo $this -> read_data($this -> socket); } } } function send_data($message) { fputs($this -> socket, $message . "\r\n", 512); } function read_ping($in) { if(strpos($in, 'PING: ') !== FALSE) { $this -> send_data('PONG: ' . substr($in, 6)); } } function read_data($data) { $in = fgets($data, 4096); $this -> read_ping($in); return $in; } } $irc = New ircBot(); $irc -> server = 'irc.freenode.net'; $irc -> port = '6667'; $irc -> password = ''; $irc -> nickname = 'Kejsarns-bot'; $irc -> username = 'Kejsarns-bot'; $irc -> login_type = '* 0'; $irc -> real_name = 'The Devine bot'; $irc -> channel = '#kejsarn-leker'; $irc -> start_bot(); ?>

Är f.ö. ny med OOP.

EDIT: Ändrade till PHP5.

Permalänk
Hedersmedlem

Kanske bör nämna ett den där bara fungerar i PHP5, public, protected osv finns inte i PHP4.

EDIT: Och det är ganska dumt att ha JOIN inuti while-loopen, då försöker den ju joina kanalen flera gånger.
EDIT2: Såg just att den andra PHP-lösningen också var PHP5-specifik (stream_socket_client).
EDIT3:
Ok, nu är den här boten inte klar men jag kan ge ett smakprov på vad som kommer.

Features:

  • Färgad output till terminalen (kommer att bli valfri).

  • Stöd för flera kanaler med tillhörande lösenord.

  • Interaktering med boten, nuvarande kommandon: say, join, part, kick, mode och quit, för närvarande existerar ingen sorts registrering mot boten så alla kan utnyttja dessa kommandon, detta ska självklart ändras.

  • Koden är modulär, detta innebär dock inte att moduler kan laddas dynamiskt under körning.

  • Hooks, gör det lätt att ändra beteendet vid olika händelser.

Vad som kommer:

  • Stöd för flera nicknames.

  • Någon sorts registrering mot boten så att inte vem som helst ska kunna utnyttja botens kommandon.

  • Loggning till fil.

  • Valfri färgning av outputen till terminalen.

  • Konfigurationsfil.

Detta är vad jag har i tankarna för närvarande iaf, jag kommer antagligen att komma på mer saker.

Kod: http://distopic.net/mlbot/

Visa signatur

Vim
Kinesis Classic Contoured (svart), Svorak (A5)
Medlem i signaturgruppen Vimzealoter.

Permalänk
Medlem

Nice jobbat mOREC

Permalänk
Medlem

Riktigt snyggt m0REc! Fick lite idéer om hur jag ska göra om min när jag fick se din. Den gör nästan exakt samma som din just nu, fast den har några saker som din inte har och vice versa. Vad är det för språk?

Visa signatur

"Sleep is one of those funny things about being a human being" - Marshall Brain
"Mike broke the hubble, Mike broke the hubble" - Mystery Science Theater 3000
"Det finns inget som kan kallas skrot!" säger Mulle Meck, "bara gamla saker som går att använda på nya sätt. Rulla ut och rulla på."

Permalänk
Medlem

O'Caml skulle jag tippa.

Permalänk
Hedersmedlem

O'Caml är korrekt.

Visa signatur

Vim
Kinesis Classic Contoured (svart), Svorak (A5)
Medlem i signaturgruppen Vimzealoter.

Permalänk
Medlem

ruby för qnet :X

require 'socket' sock = TCPSocket.new("port80.se.quakenet.org", "6667") sock.puts("NICK serpbot") sock.puts("USER a a a :a") connected = false while (line = sock.gets) if (line.index('PING') == 0) line[1] = 'O' sock.puts(line) if (!connected) sock.puts("JOIN #sweclockers") sock.puts("PRIVMSG #sweclockers :hej :D") connected = true end end end

Permalänk

Tänkte att jag kanske får låna tråden lite. jag söker nämligen en bot eller script som gör att om en user med rätt auth (xx.uses.quakenet.org eller hur den nu är formad.) och om den är rätt så ska andvändaren se en lista över filer och kunna ladda upp/ner filer till den mappen
är det något som är möjligt... så om någon orkar göra sig besväret eller vet en sån så säg till

ha'de

Visa signatur

"Det är en laZzer som läZzer skivorna sen skjuter den ut bilden i kablarna som dunkar in i tävän!"

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av call3
Tänkte att jag kanske får låna tråden lite. jag söker nämligen en bot eller script som gör att om en user med rätt auth (xx.uses.quakenet.org eller hur den nu är formad.) och om den är rätt så ska andvändaren se en lista över filer och kunna ladda upp/ner filer till den mappen
är det något som är möjligt... så om någon orkar göra sig besväret eller vet en sån så säg till

ha'de

Det är möjligt, men menar du ladda upp genom DCC?
Lista filer är inte så svårt, och inte heller kolla auth

Permalänk
Medlem

Livar upp den här tråden igen för det vore roligt med fler exempel

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av m0REc
if ($d =~ m/^(:([^ ]+))?[ ]*([^ ]+)[ ]+:?([^ ]*)[ ]*:?(.*)$/) {
my $prefix = $1;
my $command = $3;
my $arg = $4;
my $args = $5;

# Extract nickname from the prefix
$prefix =~ m/:(.+)!.+/;
my $who = $1;

Är det stora regexet perl-specifikt?
Jag får det inte att funka med Mono (C#)

Visa signatur

Också känd som eml
* C99, OSX86, PHP, Python, Warsow

Permalänk
Medlem

Bah, jag som hade en halvfärdig i perl för några år sen!

Visa signatur

Kör väl en klassisk signatur:
9900K @ 5GHz/128GB 3200MHz DDR4/3x1TB NVME/6800XT på Aorus Z390 Elite
Samsung C34F791, Svive 34C801, Xiaomi 34", Logitech MX Master 3 + G512...
Behöver för jobb, ej gamer.

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av SuIZo
Är det stora regexet perl-specifikt?
Jag får det inte att funka med Mono (C#)

Jo, det är PCRE (Perl Compatible Regular Expressions), om du kollar på min andra kod (O'Caml exempelvis) så hittar du standardregexp som kanske fungerar i C#.
Å andra sidan så tycker jag att det är skumt om C# inte har stöd för det där regexpet för jag använder knappast något PCRE-specifikt (mer än att jag inte har \ framför ( och ) vid grupperingar vilket man har i standardregexp) så jag tycker nästan att det borde fungera med POSIX-regexp också.

Visa signatur

Vim
Kinesis Classic Contoured (svart), Svorak (A5)
Medlem i signaturgruppen Vimzealoter.