Database works but has "errors in code"

Question: So im in the middle of practicing python in the way of making a discord bot in a server I help run. The dev has helped coach me through alot of it but is unfamilair with Replit. Ive just converted variables stored in .txt files over to Replits own databases system. It all seemed pretty smooth and it all works as intended. However, my Repl seems to have “errors”, saying that “db” is “Object of type “None” is not subscriptable”. The AI debugging can’t seem to help me fix it and the Dev who is coaching me say it all looks fine to him after looking up how to set up the imports for “db”. I’ve even tried various instances of calling a variable from the database throughout my code to see where it could lose this attribute.
I even tried calling “db” directly after the import and it still comes up with the error.

cg6Uu9h0j5
Replit_Cv15bPt0fy
Replit_bicKDMZDAD

PS. Ignore the random mentions of ‘p***’, its just a server wide meme/inside joke.

import os

import disnake
from disnake.ext import commands
from replit import db

# Create a variable called TOKEN and assign it to the bot
# Checks whether the bot in in testing mode or not to activate the correct token
BOT_ON_TEST = 0  # MAKE SURE THIS IS "0" BEFORE DEPLOYING!!!

TOKEN = os.environ['BOT_TOKEN']
if BOT_ON_TEST == 1:
  TOKEN = os.environ['TEST_TOKEN']
  
# create a variable called intents and assign it to disnake.Intents.all()
# this will allow the bot to access all the events in the discord server
intents = disnake.Intents.all()

# create a variable called bot and assign it to commands.Bot()
# this lets you "define" the bot and set the command prefix to whatever you want
bot = commands.Bot(command_prefix="%", description="Spoon Bot", intents=intents)

#### VARIBALES ####

# Server role ID's
""" flip_guild = bot.get_guild(552272606678745099)
admin_role = flip_guild.get_role(591009571011559530)
servermod_role = flip_guild.get_role(1059534907589804043)
publicmod_role = flip_guild.get_role(1055625560547672144) """

# UserId's of specific members
spoon_id = 155453865943236608
shake_id = 546159567042510851
beef_id = 110095251149959168

# Channel ID's
spoon_counter = 1186083375128256633

# Discord's character limit
discord_char_limit = 2000
database = db.keys()
if 'counter_var' not in database:
  db['counter_var'] = 0
if 'p***_counter' not in database:
  db['p***_counter'] = 0

#### FUNCTIONS ####

# Function which is part of the "message to file" comparison for the counter channel.
def count_match(input):
  num_to_check = int(input)
  print(f"|| {db['counter_var']}", end=" ")
  if num_to_check == db['counter_var']:
    db['counter_var'] = db['counter_var'] + 1
    print(" (Matched)")
    return True
  else:
    print(" (Not Matched)\n")
  return False


# Create an event called on_ready,
# which is triggered when the bot is started and ready to go.
@bot.event
async def on_ready():
  print("The bot is online!")
  print(f"REPLIT_DB_URL: {os.getenv('REPLIT_DB_URL')}")
  print(f"Spoon counter: {db['counter_var']}")
  print(f"P*** counter: {db['p***_counter']}")

#### BOT COMMANDS ####

# A command to set the 'counter_var.txt' file back to 1
@bot.command()
@commands.has_permissions(administrator=True)
async def resetcounter(ctx):
  if BOT_ON_TEST == 0:
    if ctx.channel.id == spoon_counter:
      db['counter_var'] = 1
      await ctx.channel.send(f"Counter has been reset to: {db['p***_counter']}\n")
    else:
      await ctx.channel.send("This command can only be used in the counter channel!")

#### DISCORD MESAGES ####

# The bot is "reading" every message to see if it cares about it.
@bot.event
async def on_message(message):
  # if the message is from the bot, ignore it
  if message.author == bot.user:
    return

  # We need to add this line to make sure the bot processes commands.
  # Without this line, the bot won't process "proper" commands
  # like the "%" commands we created earlier.
  await bot.process_commands(message)

  # The bot is checking for an @mention of a user.
  if BOT_ON_TEST == 0\
  and bot.user.mentioned_in(message):
    await message.add_reaction('<:pepe_SUS:1127261227211567125>')
    return

    # This is the block that checks the "spoon-counter" channel for messages.
  if BOT_ON_TEST == 0\
  and message.channel.id == spoon_counter:
    try:
      num = int(message.content)
      print(f"{message.channel.name}: {num}", end=" ")
      if count_match(num) is True: # function to check if "num" matched the db
        await message.add_reaction('\u2705')
      else:
        await message.add_reaction('\u274C')
    except ValueError:
      if "%resetcounter" not in message.content.lower():
        print(
            f"{message.channel.name}: '{message.content}' is not a number.\n")
        await message.add_reaction('\u274C')

    # Checks for "69" and makes sure its not an emoji (containing "<" and ">")
    # also checks to make sure its only in the "counter" channel
  if BOT_ON_TEST == 0\
  and "69" in message.content.lower()\
  and "<" not in message.content.lower()\
  and ">" not in message.content.lower()\
  and message.channel.id == spoon_counter:
    await message.add_reaction('<:Nice:1186045093585617087>')

    # checks for "p***" in a message sent in any channel except "spoon-counter"
  if BOT_ON_TEST == 0\
  and "p***" in message.content.lower()\
  and message.channel.id != spoon_counter:
    print(f"{message.channel.name}: P*** detected in '{message.content}'",
          end=" ")
    p***_count = 0
    index = 0
    length = 4
    for _i in message.content.lower():
      word_to_check = str(slice(message.content.lower()[index:length]))
      index += 1
      length = index + 4
      if "p***" in word_to_check:
        p***_count += 1
    print(f"- ({p***_count})")
    p***_emoji_len = len(str('<:BeefW:1034527400777748480>'))
    max_p***_count = int(discord_char_limit // p***_emoji_len)
    if p***_count > max_p***_count:
      await message.channel.send('<:BeefW:1034527400777748480>' * max_p***_count)
    else:
      await message.channel.send('<:BeefW:1034527400777748480>' * p***_count)
  else:
    return
  db['p***_counter'] = db['pi***_counter'] + p***_count
  print(f"Culumative p***: {db['p***_counter']}")

# Database Testing #

"""     elif "p***" in message.content.lower()\
      and message.channel.id != spoon_counter:
        await message.channel.send('<:BeefW:1034527400777748480>') """

# Reacts with emoji if userID matched for EVERY message sent.
"""    elif message.author.id == beef_id:
        await message.add_reaction('<:BeefW:1034527400777748480>')"""

# run the bot with the TOKEN variable we created earlier
# this is what actually starts the bot
bot.run(TOKEN)

While I’m not sure why it’s bugged in the editor, I’d just like to note that Replit DB isn’t usable from deployments yet AFAIK.

Try replacing your from replit import db with this:

from replit.database import Database, db_url
db = Database(db_url)
3 Likes

Perfect thank you. Although it worked as:

from replit.database import Database

db = Database("URL")

It did have an issue with ..import Databse, db_url (wasn’t defined)

This removed all of the red errors from my code and deploys fine too.
With some testing after deployment, I can confirm that my Database works as intended. I used https://replit-database-viewer.luisafk.repl.co/ and refreshed it now and again to check.

FYI unless I was doing it wrong, it doesnt like the “URL” stored as a secret…
EDIT: I was doing it wrong. You have to force the “URL” into a string like this

from replit.database import Database

db = Database(str(os.environ['DB_URL_SECRET']))

Gotta keep that info safe kids :slight_smile:

The default DB URL changes regularly (perhaps for security reasons), hence this.


the typechecker wants you to ensure that db is not None ( ← that a DB URL is available). So, go back to using the db normally, except before any code which accesses db, you need to have:

assert db is not None, "runner is not logged in"
4 Likes

Wow thank you so much. That seems to have done the trick! Like i said before the code worked as intended and didn’t throw any errors or anything and the code was able to interact with the database like there were no “errors” present.

image
section of my code now (no red😊)

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.