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...).
Related
Running on Windows 7 and using PyCharm 2016.2.3 if that matters at all.
Anyway, I'm trying to write a program that sends an email to recipients, but I want the console to prompt for a password to login.
I heard that getpass.getpass() can be used to hide the input.
Here is my code:
import smtplib
import getpass
import sys
print('Starting...')
SERVER = "localhost"
FROM = "my#email.com"
while True:
password = getpass.getpass()
try:
smtpObj = smtplib.SMTP(SERVER)
smtpObj.login(FROM, password)
break
except smtplib.SMTPAuthenticationError:
print("Wrong Username/Password.")
except ConnectionRefusedError:
print("Connection refused.")
sys.exit()
TO = ["your#email.com"]
SUBJECT = "Hello!"
TEXT = "msg text"
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
smtpObj.sendmail(FROM, TO, message)
smtpObj.close()
print("Successfully sent email")
But when I run my code, here is the output:
Starting...
/Nothing else appears/
I know the default prompt for getpass() is 'Password:' but I get the same result even when I pass it a prompt string.
Any suggestions?
EDIT: The code continues to run indefinitely after it prints the string, but nothing else appears and no emails are sent.
For PyCharm 2018.3
Go to 'Edit Configurations' and then select 'Emulate terminal in output console'.
Answer provided by Abhyudaya Sharma
The problem you have is that you are launching it via PyCharm, which has it's own console (and is not the console used by getpass)
Running the code via a command prompt should work
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.
I have a Python script that loops through a list of 8 different machines and does a copy, execute, and test. I would like to receive an email after each loop. **I'm not sure what to google for this. I would appreciate any ideas that will help me with my task.
I am aware of the smtplib module, just not how to perform a certain task with it.
I did indeed check the handy search engine and found no previous questions that provided answers
Question: how would one break in the middle of a loop, send an email, then continue with the loop??????
I have an email when the script starts and an email when the script ends. I just want to be notified as the script progresses or if it fails.
Thank you in advance.
You're looking for Python's smtp library.
The example from the documentation is this:
import smtplib
def prompt(prompt):
return raw_input(prompt).strip()
fromaddr = prompt("From: ")
toaddrs = prompt("To: ").split()
print "Enter message, end with ^D (Unix) or ^Z (Windows):"
# Add the From: and To: headers at the start!
msg = ("From: %s\r\nTo: %s\r\n\r\n"
% (fromaddr, ", ".join(toaddrs)))
while 1:
try:
line = raw_input()
except EOFError:
break
if not line:
break
msg = msg + line
print "Message length is " + repr(len(msg))
server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
Use the built-in email package to create your message if there's anything nonstandard you need to do with MIMEtypes/etc. Use the built-in smtplib package to send it (and create it if you don't have to do anything fancy).
I'm building an IRC bot in Python for fun. It is supposed to accept commands prefixed with '!' and act on them. The function below is used to parse commands received in an IRC message.
def parse_cmd(self, sender):
#Admin Commands
if sender == self.owner:
if self.command == 'quit':
send_bufr = "QUIT %s\r\n" %(self.channel)
self.sock.send(bytearray(send_bufr, "utf-8"))
self.sock.close()
sys.exit(1)
if self.command == 'hi':
print("Run: Hi")
send_bufr = "PRIVMSG %s :Hello %s" %(self.channel, sender)
print(send_bufr)
self.sock.send(bytearray(send_bufr, "utf-8"))
return
else:
return
else:
return
The exclamation points are parsed earlier and the function uses self.command as the command which is also set earlier. The following code is used to set the USER, NICK, and to join a channel and self.sock.send works fine here:
#Send NICK self.nick to set NICK
send_bufr = ("NICK %s \r\n") %(self.nick)
self.sock.send(bytearray(send_bufr, "utf-8"))
print("Set Nick to %s" %(self.nick))
#Send USER to set USER
send_bufr = ("USER %s 8 * :S0lder \r\n") %(self.nick)
self.sock.send(bytearray(send_bufr, "utf-8"))
print("Set USER to %s 8 :S0lder" %(self.nick))
#JOIN self.channel
send_bufr = ("JOIN %s \r\n") %(self.channel)
self.sock.send(bytearray(send_bufr, "utf-8"))
print("Joined %s" %(self.channel))
time.sleep(5)
However In the function earlier and any instances of self.sock.send() after the initial connection are not sent until the '!quit' command is given, at which point all of the messages that were supposed to be sent earlier are sent. Why is this? Am I misunderstanding the proper way to use sockets?
Edit: I'm connected to the same channel with an IRC client and the messages appear in the channel only after I give the !quit command.
In his comment on my question, Winston Ewert was correct. The socket.send should have read:
send_bufr = "PRIVMSG %s :Hello %s\r\n" %(self.channel, sender)
print(send_bufr)
self.sock.send(bytearray(send_bufr, "utf-8"))
A dumb mistake on my part to leave out the terminator. Thanks to everyone who helped.
Try:
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
which should flush the buffer pretty much immediately.
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