-
Notifications
You must be signed in to change notification settings - Fork 0
/
bot.py
190 lines (165 loc) · 10.4 KB
/
bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# LIBRARY IMPORTS
import time
import os
from pathlib import Path
import re
import discord
from discord.ext.commands import Bot
from discord import Intents
# LOCAL IMPORTS
import nextlevel_config as nc
import wrapper
import secret
# GLOBAL VARIABLES
# Global Wrapper instance
WRAPPER = wrapper.Wrapper()
# intents and bot (used by discord.py)
intents = Intents.all()
bot = Bot(intents=intents, command_prefix="!")
# Executes upon first initialization of bot
@bot.event
async def on_ready():
# Define the scope of GLOBAL VARIABLES
global WRAPPER
if nc.ENABLE_CONSOLE_OUTPUT:
print("Bot connected as {}".format(bot.user))
# Executes whenever a new message appears on a server in which the bot has membership
@bot.event
async def on_message(message):
# Define the scope of GLOBAL VARIABLES
global WRAPPER
# DEFAULT alert message (sent by bot into channel)
alertMessage = "Thanks {}! Your ETH address has been detected and stored!".format(message.author.mention)
# failedRegistration: Default False, but will be set to True if anything about the user registration process fails
failedRegistration = False
# Check if the mesage is the proper length
if (len(message.content) == nc.ADDRESS_STRING_LENGTH):
# If the message FAILS the full set of address checks
if not checkAddressValidity(message.content):
# Warn the user if their message was not a valid address despite the correct length
await message.channel.send("Hey {}, you posted a {}-character message beginning with \"{}\", but it is not a valid {} address.\nDid you mean to share your {} address? If so, please try again!".format(message.author.mention, nc.ADDRESS_STRING_LENGTH, nc.ADDRESS_STRING_PREFIX, nc.ASSET_SYMBOL_STRING, nc.ASSET_SYMBOL_STRING))
# If the message PASSES all address checks
else:
# Optional print statement for output readability
if nc.ENABLE_CONSOLE_OUTPUT:
print()
# Stores an all-uppercase version of the user's submitted address
compAddress = message.content.upper()
# Placeholder for overwriting userList contents
overwriteIndex = -1
# Placeholder for previous LastTimestamp/WalletAddress, if overwritten
prevLastTimestamp = ""
prevWalletAddress = ""
# Get the current timestamp
currentTimestamp = str(time.time())
# If the Discord User ID already exists within the userDict
if message.author.id in WRAPPER.userDict:
# Set the overwriteIndex equal to the user's index within userList
overwriteIndex = WRAPPER.userDict[message.author.id]
# Set the values of the prev variables
prevLastTimestamp = WRAPPER.userList[overwriteIndex][3]
prevWalletAddress = WRAPPER.userList[overwriteIndex][4]
# Update the LastTimestamp (index 3), WalletAddress (index 4) and LastUsername (index 6) values within the relevant row of userList
WRAPPER.userList[overwriteIndex][3] = currentTimestamp
WRAPPER.userList[overwriteIndex][4] = compAddress
WRAPPER.userList[overwriteIndex][6] = str(message.author)
# Alert the user that they've successfully updated their wallet address
alertMessage = "Hello {}! You have successfully updated your wallet address!".format(message.author.mention)
# If the Discord User has never submitted their address before
else:
# Add the user's Discord User ID to the userDict
WRAPPER.userDict[message.author.id] = WRAPPER.userCount
# A 1-D list (of mixed types) which holds the elements to be inserted into userList
# NOTE: Be aware that this list stores the ALL-UPPERCASE version of the user's wallet address
userInfo = [message.author.id, WRAPPER.userCount, currentTimestamp, currentTimestamp, compAddress, str(message.author), str(message.author)]
# Append this new "user row" to the userList list
WRAPPER.userList.append(userInfo)
# Increment userCount
WRAPPER.userCount += 1
# Alert the user that they've been successfully added to the system for the first time
alertMessage = "Welcome {}! You have successfully registered your wallet address for the first time!".format(message.author.mention)
# If the submitted wallet address does not exist within the allAddressDict, it has not previously been submitted
if compAddress not in WRAPPER.allAddressDict:
# Add the user's address to allAddressDict, paired with the Storage Index for this user
WRAPPER.allAddressDict[compAddress] = WRAPPER.userDict[message.author.id]
# Increment allAddressCount
WRAPPER.allAddressCount += 1
# Otherwise, this is a special case handled dependent on whether the wallet address already belongs to the current user
else:
# If the user is resubmitting their own existing wallet address
if compAddress == prevWalletAddress:
# Alert the user of successful detection and storage of their ETH address
alertMessage = "Hello {}! You are already registered under that address, there's no need to resubmit!".format(message.author.mention)
# If the user is resubmitting an address which is not currently theirs, but which they PREVIOUSLY submitted
elif WRAPPER.allAddressDict[compAddress] == WRAPPER.userDict[message.author.id]:
# Alert the user of successful reversion back to a previously-used address
alertMessage = "Hello {}! You have successfully updated your wallet address (back to a value which you previously used)!".format(message.author.mention)
# If another user is trying to submit an already-claimed wallet address
else:
# Reset the changed values within userList
# If the user was attempting to overwrite their own existing value, just revert the change
if overwriteIndex != -1:
WRAPPER.userList[WRAPPER.userDict[message.author.id]][3] = prevLastTimestamp
WRAPPER.userList[WRAPPER.userDict[message.author.id]][4] = prevWalletAddress
# NOTE: We explicitly do not revert their username, since this is a useful update to keep regardless
# TODO: Consider whether to skip the reversion of the LastTimestamp update as well
# Set failedRegistration to True
failedRegistration = True
# Print information (to the console) about the failed registration
if nc.ENABLE_CONSOLE_OUTPUT:
print("EXISTING USER FAILED TO UPDATE ADDRESS DUE TO UNAVAILABILITY OF WALLET ADDRESS.\nUSER INFORMATION REMAINS AS PREVIOUS, SHOWN BELOW:")
print(WRAPPER.userList[WRAPPER.userDict[message.author.id]])
# Alert the user of successful detection and storage of their ETH address
alertMessage = "Hello {}! You tried to change your address to an address which has already been claimed!\nThis is prohibited, so your address will instead remain its previous value of {}.".format(message.author.mention, prevWalletAddress)
# Otherwise, the user was trying to newly join with an already-used address
else:
# As a result, we remove this user's entire record
WRAPPER.userList.pop()
# Decrement the userCount
WRAPPER.userCount -= 1
# Remove the user from userDict
WRAPPER.userDict.pop(message.author.id, None)
# Set failedRegistration to True
failedRegistration = True
# Print information (to the console) about the failed registration
if nc.ENABLE_CONSOLE_OUTPUT:
print("NEW USER FAILED TO REGISTER DUE TO UNAVAILABILITY OF WALLET ADDRESS.")
# Alert the user of successful detection and storage of their ETH address
alertMessage = "Hello {}! You tried to register with an address which has already been claimed!\nThis is prohibited, so you haven't yet been added to the system. Please submit a unique address of your own!".format(message.author.mention)
# If registration DID NOT FAIL
if not failedRegistration:
# Print information (to the console) about the new data
if nc.ENABLE_CONSOLE_OUTPUT:
print("NEW WALLET ADDRESS RECEIVED AND ASSIGNED TO THE FOLLOWING ROW:")
print(WRAPPER.userList[WRAPPER.userDict[message.author.id]])
# Save the USER and ADDRESS files locally
WRAPPER.saveUsers()
WRAPPER.saveAddresses()
# AMAZON WEB SERVICES S3 BUCKET SAVING (UPLOADING)
WRAPPER.uploadS3()
# Alert the user of successful detection and storage of their ETH address
await message.channel.send(alertMessage)
await bot.process_commands(message)
def checkAddressValidity(stringIn):
# Gets the length of the prefix and remainder
prefixLength = len(nc.ADDRESS_STRING_PREFIX)
remainderLength = nc.ADDRESS_STRING_LENGTH - prefixLength
# CHECK 1: STRING LENGTH
if not (len(stringIn) == nc.ADDRESS_STRING_LENGTH):
return False
# CHECK 2: PREFIX MATCHING
if not (stringIn[0:prefixLength].upper() == nc.ADDRESS_STRING_PREFIX.upper()):
return False
# CHECK 3: REGULAR EXPRESSION ON REMAINDER OF STRING
reString = "([" + nc.ADDRESS_STRING_CHARS + "]{" + str(remainderLength) + "})"
reResult = re.search(reString, stringIn[prefixLength:])
# This statement is entered if re.search() returned None (did not find a match)
if not reResult:
return False
# Returns True now that all checks have passed
return True
def main():
# Use the GLOBAL value of WRAPPER
global WRAPPER
bot.run(WRAPPER.token)
main()