Usually I would attempt something like this with the twisted library, but that isn't available for python 3 - so I attempted it using the sockets library. The code does establish a connection, but the server quickly responds with "no ident response". I don't have much network programming experience, so I would appreciate it if someone could point out the error I'm making here. I'm also quite aware that there are functions/other code that aren't used, or that Ive used inconsistently. I just thought I would paste the entirety of my code here in case its relevant.
import socket
server = "irc.freenode.net"
channel = "put channel here"
nickname = "put nickname here"
def encode(text):
return text.encode("ascii")
def ping():
irc_socket.send(encode("PONG :pingis\n"))
def send_message(chan, msg):
irc_socket.send(encode("PRIVMSG " + chan + " :" + msg + "\n"))
def join_channel(chan):
irc_socket.send(encode("JOIN " + chan + "\n"))
def login(username='user', realname='Pythonist', hostname='Helena', servername='Server'):
irc_socket.send(encode("USER %s %s %s %s" % (username, hostname, servername, realname)))
irc_socket.send(encode("NICK " + nickname))
irc_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
irc_socket.connect((server, 6667))
login()
join_channel(channel)
while True:
buffer = irc_socket.recv(1024)
msg = str.split(str(buffer))
if msg[0] == "PING":
irc_socket.send("PONG %s" % msg[1])
print(msg)
The code was originally from: http://wiki.shellium.org/w/Writing_an_IRC_bot_in_Python and Ive made minor changes.
Teensy tiny little problem that’s causing all the trouble: you’re missing newlines in login. "USER %s %s %s %s" should be "USER %s %s %s %s\n" and "NICK " + nickname should be "NICK " + nickname + "\n". The server looks up your ident and doesn’t find it, and the next step after that is for you to register, but you never send it a complete line, so it keeps waiting… and waiting…
Ident is UNIX service which nobody has been using for twenty years or so.
It was used to identify the remote user when doing terminal server to remote server connections in terminal applications. Ident is no way safe for modern internet, so nobody is using it anymore.
So you have hit the ghost of the past. Also, as mentioned in the above answer, if you send correct NICK command the IRC server is happy with your client.
Related
I'm trying to add to my python IRC bot a function that when I type "join #channel-name" on IRC, the bot will join the channel.
Here's my code:
# IRC bot written by syrius
import socket
server = "irc.freenode.net" # IRC server
channel = "#syrius-test" # Channel
botnick = "syrius-bot" # Nickname of the bot
master = "syrius_" # Nickname of the bot's master
exitcode = "bye " + botnick #Text that we will use to make the bot quit
def ircwrite(message):
global ircsock
ircsock.send(str(message).encode('latin-1', 'ignore'))
def ping():
ircwrite("PONG :pingis\n")
def sendmsg(chan , msg):
ircwrite("PRIVMSG "+ chan +" :"+ msg +"\n")
def joinchan(channel):
ircsock.send(bytes("JOIN "+ channel + "\n"))
def join():
ircsock.send(bytes("JOIN %s"))
def hello():
ircwrite("PRIVMSG "+ channel +" :Hello!\n")
def quitting():
ircwrite("PRIVMSG "+ channel +" :Okay boss, leaving now.\n")
ircsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ircsock.connect((server, 6667))
ircwrite("USER "+ botnick +" "+ botnick +" "+ botnick +" :IRC bot coded by syrius.\n")
ircwrite("NICK "+ botnick +"\n")
joinchan(channel)
while 1:
ircmsg = ircsock.recv(2048).decode() # receive data from the server
ircmsg = ircmsg.strip('\n\r') # removing any unnecessary linebreaks.
print(ircmsg) # Here we print what's coming from the server
name = ircmsg.split('!',1)[0][1:] # We split out the name
if ircmsg.find(":Hello "+ botnick) != -1: # If we can find "Hello Mybot" it will call the function hello()
hello()
if ircmsg.find("PING :") != -1: # if the server pings us then we've got to respond!
ping()
if name.lower() == master.lower() and ircmsg.find(":quit " + botnick) != -1:
quitting()
ircsock.send(bytes("QUIT \n", "UTF-8"))
if name.lower() == master.lower() and ircmsg.find(":join %s") != -1:
join()
main()
Of course the following code is incorrect :
line23:
def join():
ircsock.send(bytes("JOIN %s"))
line56:
if name.lower() == master.lower() and ircmsg.find(":join %s") != -1:
join()
I would like to know what should I put there so the bot can join the channel.
Any help would be very appreciated.
I see a couple of problems with this solution, my recommendation is you should probably try to use an IRC framework such as Pydle or one of the billion others that already handle protocol.
The first issue I see is using latin-1 for your encoding, generally you should be using utf-8, you could also be using whatever the server advertises in the CHARSET from the RPL_ISUPPORT reply, though that is not common anymore. Along the lines of encoding also, you could decode the IRC lines from utf-8 so you can deal with strings instead of bytes, and just reencode it at the output.
The next IRC issue would be your line ends, IRC messages should always end with CR-LS (Carriage Return-Line Feed) which would be the \r\n characters instead of just the \n.
The last thing I felt like mentioning was your string formatting, you should be using "JOIN {}".format(channel) which is the preferred string formatting method these days, unless you're using python 3.7 then you would use fstrings which are similar.
With the way you are trying to do the formatting now, you are doing it through both concatenation (eg "USER" + channel) but you are also trying to use old style string formatting through %s. If you wanted to use %s formatting the correct way would be "JOIN %s" % (channel), though these days using .format and fstrings are the preferred method.
You are missing argument. ircsock.send(bytes("JOIN %s")).
It should be like this:
ircsock.send(bytes("JOIN %s \r\n") % (channel))
I'm not getting a "Ident" Response with this IRC Connection
import sys
import time
import socket
server="irc.freenode.net"
botnick="Hidden"
channel="Hidden"
#Establish connection
irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
irc.connect((server,6667))
irc.setblocking(False)
time.sleep(1)
time.sleep(1)
irc.send(("/NICK "+botnick+"\r\n").encode('UTF-8'))
time.sleep(1)
irc.send(("/JOIN "+channel+"\r\n").encode('UTF-8'))
while 1:
time.sleep(0.1)
try:
text=irc.recv(2040)
print(text)
except Exception:
pass
if text.find("PING")!=-1:
irc.send(("Test").encode('UTF-8'))
input()
and this is the console Output
b':wilhelm.freenode.net NOTICE * :*** Looking up your
hostname...\r\n:
wilhelm.freenode.net NOTICE * :*** Checking Ident\r\n:
wilhelm.freenode.net NOTICE * :*** Found your hostname\r\n'
b':wilhelm.freenode.net NOTICE * :*** No Ident response\r\n'
It just hangs for about 5-10 seconds then says closing link to 127.0.0.1
then says b'' multiple times
Code inspired from
http://agzuniverse.blogspot.ca/2016/05/irc-bot-in-python-tutorial.html
identd RFC1413 is a service used to associate connections coming from multiuser hosts with the users who "own" those connections. It used to be more widely used, with older SMTP and NNTP servers frequently configured to log identd responses, but today it's largely fallen out of use except for IRC servers.
Originally, IRC servers checked for ident at connection, because the majority of connections were from UNIX hosts with large numbers of users, and ident allowed servers as well as channel oporators to differentiate between those users in the case of abuse.
It still functions for that purpose to this day, and is frequently required for hosts that want permission to exceed more than a very small connection limit (usually 2-5 connections). Sometimes, servers will require it even for hosts which aren't shared, because it creates a roadblock for people attempting to IRC from unsecured proxies and from systems where IRC use is prohibited.
Because identd operates on port 113, when using it with a unix-like operating system system such as Linux, you cannot start the service as a normal user - the system administrator will have to install an ident daemon. Most likely, there's one or more available in software repositories for your system. On Windows, no such notion of privileged ports exists, and IRC client software typically provides it's own built-in identd.
You are missing command before joining channel. The command is missing is USER. W/out command USER. It will wait for Ident. Then, for 5-10 secs then closing link.
In my case:
_user = ("USER %s %s bla :%s\r\n" % (self.irc_nick, self.irc_host,self.irc_nick))
self.irc_sock.send(bytes(_user, 'UTF-8'))
In your case:
irc.send('USER %i 8 * :%s\r\n' % (ident, nick))
Or even using bytes:
irc.send(bytes("USER " + botnick + " " + botnick +" " + botnick + " :python\n", "UTF-8"))
Then you send to NICKSERV IDENTIFY :
irc.send(bytes("NICKSERV IDENTIFY " + botnickpass + " " + botpass + "\n", "UTF-8"))
I am currently trying to read messages cat channels Twitch. For this, I have read some guides and I learned it had to go through the IRC Twitch. I then found a few lines of simple code.
import socket
import string
HOST="irc.twitch.tv"
PORT=6667
NICK="TwitchUsername"
IDENT="TwitchUsername"
REALNAME="TwitchUsername"
CHANNEL="#ChannelNameHere"
PASSWORD="OAuth Password here" #From http://twitchapps.com/tmi/
readbuffer=""
s=socket.socket( )
s.connect((HOST, PORT))
s.send("PASS %s\r\n" % PASSWORD)
s.send("NICK %s\r\n" % NICK)
s.send("USER %s %s bla :%s\r\n" % (IDENT, HOST, REALNAME))
s.send("JOIN %s\r\n" % CHANNEL)
while 1:
readbuffer=readbuffer+s.recv(1024)
temp=string.split(readbuffer, "\n")
readbuffer=temp.pop( )
for line in temp:
line=string.rstrip(line)
line=string.split(line)
if len(line) > 3:
print line
if(line[0]=="PING"):
s.send("PONG %s\r\n" % line[1])
However, authentication does not proceed as planned, since I get the following message:
[':tmi.twitch.tv', 'NOTICE', '*', ':Login', 'unsuccessful']
I am using a valid OAuth Chat Password, and I see no reason that justifies this failure. Do you also have an error when you try with your username? Or do you have an idea of the problem please?
Your OAuth password needs to be sent as:
PASS oauth:twitch_oauth_token
which means that if you are putting in your token in the PASSWORD variable without the oauth: prefix, you should amend the pass line to:
s.send("PASS oauth:%s\r\n" % PASSWORD)
I was seeing the same :tmi.twitch.tv NOTICE * :Error logging in.
As noted in the readme "Your nickname must be your Twitch username in lowercase".
My issue was not making the NICK exactly my twitch username in lowercase (Not a very informative notice. So hopefully this saves someone else some time...).
I need help writing a basic IRC bot that just connects to a channel.. is anyone able to explain me this? I have managed to get it to connect to the IRC server but i am unable to join a channel and log on. The code i have thus far is:
import sockethost = 'irc.freenode.org'
port = 6667
join_sock = socket.socket()
join_sock.connect((host, port))
<code here>
Any help would be greatly appreciated.
To connect to an IRC channel, you must send certain IRC protocol specific commands to the IRC server before you can do it.
When you connect to the server you must wait until the server has sent all data (MOTD and whatnot), then you must send the PASS command.
PASS <some_secret_password>
What follows is the NICK command.
NICK <username>
Then you must send the USER command.
USER <username> <hostname> <servername> :<realname>
Both are mandatory.
Then you're likely to see the PING message from server, you must reply to the server with PONG command every time the server sends PING message to you. The server might ask for PONG between NICK and USER commands too.
PING :12345678
Reply with the exact same text after "PING" with PONG command:
PONG :12345678
What's after PING is unique to every server I believe so make sure you reply with the value that the server sent you.
Now you can join a channel with JOIN command:
JOIN <#channel>
Now you can send messages to channels and users with PRIVMSG command:
PRIVMSG <#channel>|<nick> :<message>
Quit with
QUIT :<optional_quit_msg>
Experiment with Telnet! Start with
telnet irc.example.com 6667
See the IRC RFC for more commands and options.
Hope this helps!
I used this as the MAIN IRC code:
import socket
import sys
server = "server" #settings
channel = "#channel"
botnick = "botname"
irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #defines the socket
print "connecting to:"+server
irc.connect((server, 6667)) #connects to the server
irc.send("USER "+ botnick +" "+ botnick +" "+ botnick +" :This is a fun bot!\n") #user authentication
irc.send("NICK "+ botnick +"\n") #sets nick
irc.send("PRIVMSG nickserv :iNOOPE\r\n") #auth
irc.send("JOIN "+ channel +"\n") #join the chan
while 1: #puts it in a loop
text=irc.recv(2040) #receive the text
print text #print text to console
if text.find('PING') != -1: #check if 'PING' is found
irc.send('PONG ' + text.split() [1] + '\r\n') #returnes 'PONG' back to the server (prevents pinging out!)
Then, you can start setting commands like: !hi <nick>
if text.find(':!hi') !=-1: #you can change !hi to whatever you want
t = text.split(':!hi') #you can change t and to :)
to = t[1].strip() #this code is for getting the first word after !hi
irc.send('PRIVMSG '+channel+' :Hello '+str(to)+'! \r\n')
Note that all irc.send texts must start with PRIVMSG or NOTICE + channel/user and the text should start with a : !
It'd probably be easiest to base it on twisted's implementation of the IRC protocol. Take a look at : http://github.com/brosner/bosnobot for inspiration.
This is an extension of MichaelvdNet's Post, which supports a few additional things:
Uses SSL wrapper for socket
Uses server password authentication
Uses nickserv password authentication
Uses nonblocking sockets, to allow other events to trigger
Logs changes to text files to channel
#!/usr/local/bin/python
import socket
import ssl
import time
## Settings
### IRC
server = "chat.freenode.net"
port = 6697
channel = "#meLon"
botnick = "meLon-Test"
password = "YOURPASSWORD"
### Tail
tail_files = [
'/tmp/file-to-tail.txt'
]
irc_C = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #defines the socket
irc = ssl.wrap_socket(irc_C)
print "Establishing connection to [%s]" % (server)
# Connect
irc.connect((server, port))
irc.setblocking(False)
irc.send("PASS %s\n" % (password))
irc.send("USER "+ botnick +" "+ botnick +" "+ botnick +" :meLon-Test\n")
irc.send("NICK "+ botnick +"\n")
irc.send("PRIVMSG nickserv :identify %s %s\r\n" % (botnick, password))
irc.send("JOIN "+ channel +"\n")
tail_line = []
for i, tail in enumerate(tail_files):
tail_line.append('')
while True:
time.sleep(2)
# Tail Files
for i, tail in enumerate(tail_files):
try:
f = open(tail, 'r')
line = f.readlines()[-1]
f.close()
if tail_line[i] != line:
tail_line[i] = line
irc.send("PRIVMSG %s :%s" % (channel, line))
except Exception as e:
print "Error with file %s" % (tail)
print e
try:
text=irc.recv(2040)
print text
# Prevent Timeout
if text.find('PING') != -1:
irc.send('PONG ' + text.split() [1] + '\r\n')
except Exception:
continue
That will open a socket, but you also need to tell the IRCd who you are. I've done something similar in perl ages ago, and I found the IRC RFCs to be very helpful.
Main RFC: http://irchelp.org/irchelp/rfc/rfc.html
Other RFCs: http://irchelp.org/irchelp/rfc/index.html
I'm trying to write a simple module that will enable sending SMS. I using bluetooth to connect to the mobile using the below example:
file: bt-sendsms.py
import bluetooth
target = '00:32:AC:32:36:E8' # Mobile address
print "Trying to send SMS on %s" % target
BTSocket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
BTSocket.connect((target, 2)) # BT Address
BTSocket.send('ATZ\r')
BTSocket.send('AT+CMGF=1\r')
#sockfd.send('AT+CSCA="+972547716507"\r') # This line changes the SMSC address - do not modify unless required
BTSocket.send('AT+CMGS="+972547877763"\r') # TO Phone Number
BTSocket.send('This is a test message - port 2.\n')
BTSocket.send(chr(26)) # CTRL+Z
print "SMS sent"
sockfd.close()
print "Closed"
My problem is that I'm unable to verify or get an error code for the SMS sending or any of the socket operation.
Any referral to the right direction will be appreciated
From the Python you look like you are opening any old RFCOMM channel and hoping it will magically take the AT commands and do the messaging.
I think (and I could be wrong) that you need to connect to a specific profile/sevice channel and I think for SMS it is the the Messaging Access Profile (MAP), which is not yet standardised so finding a phone with it on, well I won't say impossible but very, very unlikely. Otherwise, some phones will support AT commands for messaging but this is outside the specs e.g. I have it on authority that Sony-Ericson phones will support it though the Dial-Up Networking profile (DUN).
So, first of all, does your mobile device support some out of spec AT commands for SMS and if so, on a certain profile or on an ad-hoc proprietary one? Next, you need to connect to that profile.
You can browse the supported services etc... using the following Python (checks all surrounding BT devices)...
import bluetooth
def whats_nearby():
name_by_addr = {}
nearby = bluetooth.discover_devices(flush_cache=True)
for bd_addr in nearby:
name = bluetooth.lookup_name( bd_addr, 5)
print bd_addr, name
name_by_addr[bd_addr] = name
return name_by_addr
def what_services( addr, name ):
print " %s - %s" % ( addr, name )
for services in bluetooth.find_service(address = addr):
print "\t Name: %s" % (services["name"])
print "\t Description: %s" % (services["description"])
print "\t Protocol: %s" % (services["protocol"])
print "\t Provider: %s" % (services["provider"])
print "\t Port: %s" % (services["port"])
print "\t service-classes %s" % (services["service-classes"])
print "\t profiles %s" % (services["profiles"])
print "\t Service id: %s" % (services["service-id"])
print ""
if __name__ == "__main__":
name_by_addr = whats_nearby()
for addr in name_by_addr.keys():
what_services(addr, name_by_addr[addr])
Once you find the correct service/profile, your next problem will be negotiating security (pin code for pairing), which I haven't worked out how to do yet!
See the www.bluetooth.org for all your Bluetooth needs!