Search code examples
python-3.xpython-3.6discorddiscord.py

Logging in as user using discord.py


I am trying to make some simple program, showing received messages through the terminal. Now I am trying to ask the user for their email address and password for the login, but some errors occur, which I do not quite understand. This is what my code looks like:

import discord


class DiscordClient(discord.Client):
    def __init__(self, *args, **kwargs):
        discord.Client.__init__(self, **kwargs)

    async def on_ready(self):
        print('Success!')


if __name__ == '__main__':
    dc = DiscordClient()
    dc.login(input('email : '), input('password : '), bot=False)
    dc.run()

and the error is:

Traceback (most recent call last):
  File "[...]/Main.py", line 16, in <module>
    dc.run()
  File "[...]/lib/python3.6/site-packages/discord/client.py", line 519, in run
    self.loop.run_until_complete(self.start(*args, **kwargs))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py", line 466, in run_until_complete
    return future.result()
  File "[...]/lib/python3.6/site-packages/discord/client.py", line 490, in start
    yield from self.login(*args, **kwargs)
  File "[...]/lib/python3.6/site-packages/discord/client.py", line 418, in login
    raise TypeError('login() takes 1 or 2 positional arguments but {} were given'.format(n))
TypeError: login() takes 1 or 2 positional arguments but 0 were given
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x103881fd0>

So, what am I doing wrong, or what should code look like? All I was doing was write an on_message() and some basic commands like send_message().


Solution

  • client.login is a coroutine so it should be (untested) :

    await dc.login(input('email : '), input('password : '), bot=False)
    

    Note that in this case, bot parameter is not needed. However, to use client.login, you need to use the client loop. To avoid that, you can simply do:

    dc.run(email, password)
    

    Which will both login and connect and then start the loop.

    After that you can (in the on_ready function) get a desired server from dc.servers and a suitable channel to send there, for example, a 'Hello message' with dc.send_message.

    When you are done with the connection, do self.close() from within the DiscordClient class.

    Working example for Python 3.4 (replace keywords as necessary for Python 3.6)

    import discord
    import asyncio
    import datetime
    
    
    class DiscordClient(discord.Client):
        def __init__(self, *args, **kwargs):
            discord.Client.__init__(self, **kwargs)
    
        @asyncio.coroutine
        def on_ready(self):
            servers = list(self.servers)
            for server in servers:
                if server.name == 'My server':
                    break
    
            for channel in server.channels:
                if channel.name == 'general':
                    break
    
            now = datetime.datetime.now()
            yield from self.send_message(channel, 'Api Success! at ' + str(now))
            print('Success!')
            yield from self.close()
    
    
    if __name__ == '__main__':
        dc = DiscordClient()
        email = input('email : ')
        password = input('password : ')
        dc.run(email, password)