Creating a simple IRC bot in python. Having trouble - python

So a few hours ago I decided to try my hands on sockets with python and build a simple irc bot. So far I'm having some trouble getting it connected to the server. I get the following erros:
b":irc.ku.cx 439 * :Please wait while we process your connection.\r\n:irc.ku.cx NOTICE AUTH :*** Couldn't look up your hostname (cached)\r\n"
b':irc.ku.cx NOTICE AUTH :*** Checking Ident\r\n'
b':irc.ku.cx NOTICE AUTH :*** No Ident response\r\n'
After that it stalls out. But about a minute of it running I suddenly get an endless amount of b"", each in a new line (probably something to do with the while loop in the code). This is my code:
import socket
server = 'irc.rizon.net'
channel = '#linux'
nick = 'MyBot'
port = 6667
ircsock = socket.socket()
ircsock.connect((server, port))
ircsock.send(bytes('"NICK " + nick', 'UTF-8'))
ircsock.send(bytes('"USER " + nick + " " + nick + " " + nick + " :" + nick', 'UTF-8'))
while True:
data = ircsock.recv(2048)
print (data)
if data.find(b"PING") != -1:
ircsock.send(b"PONG :" + data.split(':')[1])
Thanks for any help you guys can provide.

As icktoofay said, there are extra quotes in your code. Also, in IRC you need to add a line break (\r\n) to the end of every command.
Replace these lines:
ircsock.send(bytes('"NICK " + nick', 'UTF-8'))
ircsock.send(bytes('"USER " + nick + " " + nick + " " + nick + " :" + nick', 'UTF-8'))
with
ircsock.send(bytes("NICK " + nick + "\r\n", 'UTF-8'))
ircsock.send(bytes("USER " + nick + " " + nick + " " + nick + " :" + nick + "\r\n", 'UTF-8'))
and it should work.
By the way, I recommend using socket.makefile() instead, which handles buffering and encoding for you. Here's your code modified to use the file interface:
import socket
server = 'irc.rizon.net'
channel = '#linux'
nick = 'MyBot'
port = 6667
ircsock = socket.socket()
ircsock.connect((server, port))
handle = ircsock.makefile(mode='rw', buffering=1, encoding='utf-8', newline='\r\n')
print('NICK', nick, file=handle)
print('USER', nick, nick, nick, ':'+nick, file=handle)
for line in handle:
line = line.strip()
print(line)
if "PING" in line:
print("PONG :" + line.split(':')[1], file=handle)
Here, I use the print function which inserts spaces and newlines automatically.

Related

Remove Duplicate IP Addresses with Scapy

I have a script to listen for incoming traffic and print out only the string “IP 1.1.1.1 53" when a packet hits the line. But now that I’m doing IP resolve on the IPs, I need to access the “ip_src” variable and only do the geolocation once on each ip, rather than resolve the same IP over and over as they come in. My current code is:
#!/usr/bin/python3
from scapy.all import *
import ipinfo
def print_summary(pkt):
if IP in pkt:
ip_src=pkt[IP].src
if UDP in pkt:
udp_sport=pkt[UDP].sport
access_token = ''
handler = ipinfo.getHandler(access_token)
match = handler.getDetails(ip_src)
c = match.details.get('city')
s = match.details.get('region')
strang = ("IP " + str(ip_src) + " " + str(udp_sport) + " " + str(c) + ", " + str(s))
print(strang)
sniff(filter="",prn=print_summary)
As you can see the “print_summary” function is called by “prn” which is called for each pkt. I basically want to mimic the functionality of uniq and sort, since they can successfully filter out duplicates from a file, but I’d like to have it all in one script.
EDIT - Trying Set():
So using the code:
from scapy.all import *
def print_summary(pkt):
if IP in pkt:
ip_src=pkt[IP].src
if UDP in pkt:
udp_sport=pkt[UDP].sport
lines_set = set(ip_src)
strang = ("IP " + str(ip_src) + " " + str(udp_sport))
if ip_src not in lines_set:
for line in lines_set:
print(line)
sniff(filter="",prn=print_summary)
I get the output: (in the terminal each character has a trailing newline)
2 . 3 5 8 0 1 2 . 4 8 0 1 . 6
This adds a set variable to keep track of which addresses you have already seen.
#!/usr/bin/python3
from scapy.all import *
import ipinfo
seen = set()
def print_summary(pkt):
if IP in pkt:
ip_src=pkt[IP].src
if UDP in pkt and ip_src not in seen:
seen.add(ip_src)
udp_sport=pkt[UDP].sport
access_token = ''
handler = ipinfo.getHandler(access_token)
match = handler.getDetails(ip_src)
c = match.details.get('city')
s = match.details.get('region')
strang = ("IP " + str(ip_src) + " " + str(udp_sport) + " " + str(c) + ", " + str(s))
print(strang)
sniff(filter="ip",prn=print_summary)
I also changed the indentation of the second if to avoid getting a traceback if somehow you would receive a packet which doesn't have the IP member; though I also updated the filter expression to hopefully prevent that from ever happening in the first place.

Python TypeError with sockets

import socket, sys, string
if len(sys.argv) !=4:
print ("UsageL ./ninjabot.py <server> <port> <channel>")
sys.exit(1)
irc = sys.argv[1]
port = int(sys.argv[2])
chan = sys.argv[3]
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.connect((irc, port))
sck.send(b'NICK ninjabot\r\n')
sck.send(b'USER ninjabot ninjabot ninjabot :ninjabot Script\r\n')
sck.send('JOIN ' + " " + chan + '\r\n')
data = ''
while True:
data = sck.recv(1024)
if data.find('PING') != -1:
sck.send('PONG ' + data.split() [1] + '\r\n')
print (data)
print (data)
I get this error in sck.send('JOIN ' + " " + chan + '\r\n') but when i try this:
sck.send(b'JOIN ' + " " + chan + '\r\n')
I get TypeError: can't concat str to bytes
I know there's similar posts with this same issue, but none of those seem to help me.
This is due to the fact that b'JOIN' is of type bytes while " " as well as chan and "\r\n" are of type str.
2 corrections:
chan = sys.argv[3].encode()
sck.send(b'JOIN ' + b" " + chan + b'\r\n')
alternatively you could just:
sck.send(b'JOIN %s\r\n' % chan.encode())
this would be the best style. Similar corrections will be need to be made later in your snippet as well. socket.send is looking for a bytes string, so ensure that all strings which you pass it are either b"" or encoded otherwise using encode()

Python IRC bot will only send 1 message

I'm writing a Twitch bot and it will only send one message to server. When executing code below "Connected" shows up in Twitch chat, "Testing" does not.
import socket
HOST = "irc.chat.twitch.tv"
PORT = 6667
NICK = "mybot"
PASS = 'oauth:mytoken'
CHANNEL = "mychannel"
def send_message(msg):
s.send(bytes("PRIVMSG #" + CHANNEL + " :" + msg + "\r\n", "UTF-8"))
s = socket.socket()
s.connect((HOST, PORT))
s.send(bytes("PASS " + PASS + "\r\n", "UTF-8"))
s.send(bytes("NICK " + NICK + "\r\n", "UTF-8"))
s.send(bytes("JOIN #" + CHANNEL + " \r\n", "UTF-8"))
send_message("Connected")
send_message("Testing")

Multiprocessing and sockets, simplified

I am trying to make my IRC bot handle multiple messages at a time, but it's not sending back messages.
Behavior: Process(target=func) is called, func() calls a function that has socket.socket().send(message) in it, but the message doesn't send. Suspect is that the socket isn't passed to the sending function.
Code:
import socket
import re
import requests
import urllib
import config # just my file of variables
import math
import time
import sys
import winsound
import string
import random
import multiprocessing
# import traceback
# CONNECTION COMMANDS
ircsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server = config.server # Server
password = config.password # Password
botnick = config.botnick # Your bots nick
adminname = config.adminname # Your IRC nickname
exitcode = config.exitcode
ircsock.settimeout(300)
def connection(host, port, password, nick, realname):
ircsock.connect((host, port))
ircsock.send(bytes("PASS " + password + "\n", "UTF-8"))
ircsock.send(bytes("USER " + botnick + " " + botnick + " " + botnick + " " + botnick + "\n", "UTF-8"))
ircsock.send(bytes("NICK " + botnick + "\n", "UTF-8"))
def ping(): # respond to server Pings.
ircsock.send(bytes("PONG :pingis\n", "UTF-8"))
print("Ponged after " + str(time.time() - last_ping) + " seconds from last ping!")
def sendmsg(msg, target): # sends messages to the target.
# it enters here, no problem
ircsock.send(bytes("PRIVMSG " + target + " :" + msg + "\n", "UTF-8")) ### At this point, when using multiprocessing, the bot fails ###
print("Sending: [" + str(msg) + "] to: " + str(target))
# MAIN
if __name__ == '__main__':
connection(server, 6667, password, botnick, botnick)
# joinchan(channel)
while 1:
# print("Connected!")
ircmsg = ircsock.recv(1024).decode("UTF-8")
ircmsg = ircmsg.strip('\n\r')
if ircmsg.find("PRIVMSG") != -1:
try:
# “:[Nick]!~[hostname]#[IP Address] PRIVMSG [channel] :[message]”
name = ircmsg.split('PRIVMSG', 1)[0].split(':')[-1].split("!")[0] # ircmsg.split('!', 1)[0][1:]
message = ircmsg.split('PRIVMSG', 1)[1].split(':', 1)[1].splitlines()[0] # .strip()[0]
me = ircmsg.split('PRIVMSG', 1)[1].split(':', 1)[0].split()[0]
# print(me)
print("name: " + name + ", message: " + message)
if len(name) < 17:
if me == botnick:
if message.find("Hi!") != -1:
process1 = multiprocessing.Process(target=sendmsg, args=("Hello!", name))
process1.daemon = True
process1.start()
if name.lower() == adminname.lower() and message.rstrip() == exitcode:
sendmsg("Bot is quitting.", name)
ircsock.send(bytes("QUIT \n", "UTF-8"))
sys.exit()
time.sleep(1)
except:
pass
elif ircmsg.find("PING") != -1:
ping()
Please word your answers as simply as possible, since I am not that experienced in Python. The code above can be run with a correct config.py file.
Format:
password = "" # password to open the server
exitcode = "" # What is typed to stop the bot
server = "" # Server
botnick = "" # Your bots nick
adminname = "" # Your IRC nickname

Python - Twitch Bot - Sending/Receiving Whispers

I wrote a simple Python twitch bot following a video tutorial, but the tutorial didn't include whisper functionality. It can currently connect to the chat of the channel I specify, but when I try to have it send a whisper nothing happens. Here's the relevant code bits:
import socket
def openSocket():
s = socket.socket()
s.connect((HOST, PORT))
message = "PASS " + PASS + "\r\n"
s.send(message.encode('utf-8'))
message = "NICK " + USER + "\r\n"
s.send(message.encode('utf-8'))
message = "JOIN #" + CHAN + "\r\n"
s.send(message.encode('utf-8'))
return s
def sendMessage(s, message):
messageTemp = "PRIVMSG #" + CHAN + " :" + message + "\r\n"
s.send(messageTemp.encode('utf-8'))
print("Sent:" + messageTemp)
def sendWhisper(s, user, message):
messageTemp = "PRIVMSG #jtv :/w " + user + " " + message
s.send(messageTemp.encode('utf-8'))
import string
from Socket import sendMessage
def joinRoom(s):
readbuffer = ""
Loading = True
while Loading:
readbuffer = readbuffer + s.recv(1024).decode()
temp = readbuffer.split('\n')
readbuffer = temp.pop()
for line in temp:
print(line)
Loading = loadingComplete(line)
def loadingComplete(line):
if("End of /NAMES list" in line):
return False;
else: return True
I've been reading a little bit about connecting to some sort of group chat in order to make this work, but I'm confused and haven't found what I'm looking for. It seems like it should be an easy fix. Any help is appreciated.
You were very close. Where you messed up is there should not be a # in front of jtv:
def sendWhisper(s, user, message):
messageTemp = "PRIVMSG jtv :/w " + user + " " + message
s.send(messageTemp.encode('utf-8'))

Categories

Resources