Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Tools

Development::Tools 3rd Party Tools for EQEMu (DB management tools, front ends, etc...)

Reply
 
Thread Tools Display Modes
  #1  
Old 04-30-2018, 09:09 PM
cubber
Discordant
 
Join Date: Apr 2006
Posts: 374
Default Reggie - A Discord Bot for Automatic Private Server Login Account Requests

I give you Reggie... A quick bot that I whipped up today to process new registrations for a private login server. It will also do password resets.

Reggie creates a new login server account when a user on the discord channel that it is monitoring types <!register newaccountname>

Reggie then checks the database to see if the account exists, if not it creates the new account for the user and uses the user's Discord ID in the email field in the loginserver_server_accounts table. It then sends a PM to the user on Discord with a randomly generated password for the account.

To process a password reset request the user must enter <!resetpwd accountname> in the discord channel. Then Reggie will verify if the account is in the database, and if so that the account is owned by the Discord user requesting the password reset. (checks the email field against the DiscordID). If all is good it will generate a new random password and PM it to the user in Discord.

Enjoy!

Cubber

Code:
#!/usr/bin/python

# Program Name: EQEMU-Login-Discord.py 
#               'Discord Registration Bot for EQEMU Login Server'
# Original Author: Cubber
# Python Version: 3.5
# Original Date: 4/30/2018
# Last Revision: 4/30/2018

# Purpose:  This program will parse input from discord and setup an account on the an EQEMU Private Login Server.

# Dependencies: Python 3 && discord module 
#               python3 -m pip install --user -U discord.py[voice] # discord module

#    This file is part of EQEMU-Login-Discord.py.

#    EQEMU-Login-Discord is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.

#    EQEMU-Login-Discord is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.

#    You should have received a copy of the GNU General Public License
#    along with EQEMU-Login-Discord.  If not, see <http://www.gnu.org/licenses/>.

import subprocess
import time
import sys
import os
import discord
import asyncio
import urllib.request
import re
import uuid

from os import listdir
from os.path import isfile, join
from discord.ext import commands

import mysql.connector
import hashlib
from datetime import date, datetime, timedelta


#### MAIN PROGRAM ####

### USER DEFINED SETTINGS ###

## Discord specific settings ##
## Obtain via 'developer mode' in Discord and by right clicking on the channel, then choose copy id ##
# sandbox chat channel ID on discord server
CHAT_ID = 'XXXXXXXXXXXXXXXXXX'

# Discord Bot TOKEN - DO NOT SHARE!
# Obtained from your Discord applications page under your registered Bot for this application
TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'

# DB Settings
DBUSER='eqemu'
DB='eqemu'
DBPWD='eqemu'
DBHOST='127.0.0.1'

### END USER DEFINED SETTINGS ###


# SQL Insert Template
add_login = ("INSERT INTO loginserver_server_accounts "
            "(AccountName,AccountPassword,AccountEmail,LastIPAddress,LastLoginDate) "
            "VALUES (%s,SHA(%s),%s,%s,%s)")


# program banner 
print("\n\nStarting The EQEMU Server Login Account Registration Discord Bot\n")
print("Press Ctrl+C to exit\n")

# start up the bot and log in to discord
client = discord.Client()

# start up the bot
@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('----------')
    await client.send_message(discord.Object(id=CHAT_ID), 'Hello, my name is Reggie.  I am here to help you setup a new account on our Private EverQuest server.  Type !reghelp for more info on creating a new login server account.  You can also type !pwdhelp for more information on resetting your login server account password.', tts=False)

# some bot commands for testing and information
@client.event
async def on_message(message):
    if message.content.startswith('!test'):
        counter = 0
        tmp = await client.send_message(message.channel, 'Calculating messages...')
        async for log in client.logs_from(message.channel, limit=100):
            if log.author == message.author:
                counter += 1
        await client.edit_message(tmp, 'You have {} messages.'.format(counter))
   
    # help info
    elif message.content.startswith('!reghelp'):
        await client.send_message(message.channel, 'Hello, my name is Reggie.  I am here to help you setup a new account on our Private EverQuest server. Please use the following syntax when registering a new login server account ( !register username ). If all goes well you will recieve a PM from me with your login server credentials.  Make sure to take note of your password, it is randomly generated!', tts=False)

    elif message.content.startswith('!pwdhelp'):
        await client.send_message(message.channel, 'Hello, my name is Reggie.  I can assist you if you forgot your login server password!  Please type ( !resetpwd accountname ) in order to generate a new random password for your account.  The new credentials with be sent to you in a PM.  Note that in the interest of account security in order to reset a login server account password the request must come from the Discord user ID that the account was originally registered with.', tts=False)
    
    # register account
    elif message.content.startswith('!register'):
        # connect to eqemu db
        cnx = mysql.connector.connect(user=DBUSER, password=DBPWD, host=DBHOST, database=DB)
        cursor = cnx.cursor(buffered=True)

        # get user input
        regmsg = message.content.split(" ")

        # parse username
        username=regmsg[1] 

        # verify username is not already in db
        query="SELECT * from loginserver_server_accounts"
        userquery=query + " WHERE AccountName='"+ username + "'"

        cursor.execute(userquery)
        if cursor.rowcount>=1:
            await client.send_message(message.channel, 'Sorry that username is already taken, please try again with !register newusername.')

        if cursor.rowcount==0:
            email=str(message.author) # Discord UserID

            # generate random password
            random = str(uuid.uuid4())
            random = random.replace("-","!")
            random = random[0:9]

            # setup database variables
            account_data = (username, random, email, '127.0.0.1', datetime.now())

            # insert new account
            cursor.execute(add_login, account_data)
            # verify that query executed or die and send error to channel
    
            # ON SUCCESS: send user confirmation and pw in PM
            content = "Your login server account has been created successfully! Here are your credentials ( Username: " + username + " - Password: " + random + " )"
            await client.send_message(message.author, content)

        # save & cleanup
        cnx.commit()
        cursor.close()
        cnx.close()

    # change password
    elif message.content.startswith('!resetpwd'):
        # connect to eqemu db
        cnx = mysql.connector.connect(user=DBUSER, password=DBPWD, host=DBHOST, database=DB)
        cursor = cnx.cursor(buffered=True)

        # get user input
        regmsg = message.content.split(" ")

        # parse username
        username=regmsg[1]

        email=str(message.author) # Discord UserID
        
        # verify username is in db
        query="SELECT * from loginserver_server_accounts"
        userquery=query + " WHERE AccountName='"+ username + "' AND AccountEmail='" + email + "'"

        cursor.execute(userquery)
        # verify user and issue new random password
        if cursor.rowcount==1:
            # generate random password
            random = str(uuid.uuid4())
            random = random.replace("-","!")
            random = random[0:9]

            # setup database variables
            account_data = (random, username, email)

            # insert new account
            update_pwd="UPDATE loginserver_server_accounts SET AccountPassword=SHA(%s) WHERE AccountName=%s AND AccountEmail=%s"
            cursor.execute(update_pwd, account_data)
    
            # ON SUCCESS: send user confirmation and pw in PM
            content = "Your login server account password has been reset! Here are your new credentials ( Username: " + username + " - Password: " + random + " )"
            await client.send_message(message.author, content)

        # no valid user by that name
        if cursor.rowcount==0:
            await client.send_message(message.channel, 'Sorry that username is not valid, please try again or register a new account with !register newusername.')

        # save & cleanup
        cnx.commit()
        cursor.close()
        cnx.close()

# run the bot using the TOKEN
client.run(TOKEN)
Reply With Quote
  #2  
Old 04-30-2018, 09:18 PM
GRUMPY
Discordant
 
Join Date: Oct 2016
Posts: 446
Default

This, in the login.ini creates accounts too, simply by logging in with your client and your "first" user/password entry.
auto_create_accounts = TRUE
BUT, this would be good for a password reset feature for those who need.(if it works good)
I don't care for "random generated" passwords myself, but some might like it.
Reply With Quote
  #3  
Old 04-30-2018, 09:30 PM
cubber
Discordant
 
Join Date: Apr 2006
Posts: 374
Default

Thanks for pointing that out. I was shooting for more of a private community with this. Ie. You have a group of friends on a Discord channel that acts as a layer of vetting as well as a basic account management utility without exposing it to the masses. So you can still leave the login.ini locked down. The idea is that the bot is running in a private discord channel with restricted access.

I went with randomly generated passwords because I could not think of any other good way to not have the user's password being exposed in the discord channel. This way the user never has to type it in and the random password is just sent to them in the PM. I did this off the cuff today, and am open to suggestions for improvement.
Reply With Quote
  #4  
Old 04-30-2018, 10:58 PM
Speedz's Avatar
Speedz
Hill Giant
 
Join Date: Oct 2004
Location: Ocean Park, WA
Posts: 186
Default

You could have the bot only read/respond in PM.
Initial command to reset the password could be sent to the bot in private.

One step further, use the date and discord ID as a hash salt in the password.
Then only give the passwords a specific TTL. Pass that time you need to get a new password.

Another thought that would require a server code change would be to have the server itself send the password to a previously entered discord user name. With a TTL of course.
__________________
Just another face in the crowd..
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 10:16 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3