Last active
January 22, 2023 20:30
-
-
Save TimelessP/72f4efa1e5b523df526ff9cf3c7de4da to your computer and use it in GitHub Desktop.
A replit db example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
https://replit.com/@TimelessP/Replit-db-experiment#main.py | |
https://gist.github.com/TimelessP/72f4efa1e5b523df526ff9cf3c7de4da | |
""" | |
from replit import db | |
from dataclasses import dataclass | |
import bcrypt | |
import getpass | |
import re | |
import datetime | |
import random | |
import time | |
import json | |
@dataclass | |
class User: | |
username: str | |
password_hash: str | |
ctime_utc: datetime.datetime | |
atime_utc: datetime.datetime | |
mtime_utc: datetime.datetime | |
is_disabled: bool = False | |
def __init__(self, | |
username: str, | |
password_hash: str, | |
ctime_utc: datetime.datetime, | |
atime_utc: datetime.datetime, | |
mtime_utc: datetime.datetime, | |
is_disabled: bool = False): | |
self.username = username | |
self.password_hash = password_hash | |
self.ctime_utc = ctime_utc | |
self.atime_utc = atime_utc | |
self.mtime_utc = mtime_utc | |
self.is_disabled = is_disabled | |
def to_dict(self): | |
return { | |
'username': self.username, | |
'password_hash': self.password_hash, | |
'ctime_utc': self.ctime_utc.isoformat(), | |
'atime_utc': self.atime_utc.isoformat(), | |
'mtime_utc': self.mtime_utc.isoformat(), | |
'is_disabled': self.is_disabled | |
} | |
@classmethod | |
def from_dict(cls, data): | |
return cls(username=data['username'], | |
password_hash=data['password_hash'], | |
ctime_utc=datetime.datetime.fromisoformat(data['ctime_utc']), | |
atime_utc=datetime.datetime.fromisoformat(data['atime_utc']), | |
mtime_utc=datetime.datetime.fromisoformat(data['mtime_utc']), | |
is_disabled=data['is_disabled']) | |
# db.clear() | |
db["inited"] = True | |
class Game: | |
def __init__(self): | |
self.username = None | |
self.is_exiting = False | |
self.action_handlers = { | |
"exit": self._exit_game, | |
"help": self._help, | |
"id": self._user_id, | |
"reset": self._reset, | |
"users": self._users_list, | |
} | |
def run(self): | |
while True: | |
self.is_exiting = False | |
time.sleep(random.uniform(0, 1)) | |
print("") | |
print("Welcome to the demo. Use demo/demo for a demo user.") | |
username = input("Enter your username: ") | |
if not re.search(r"^[a-z][a-z0-9]{2,15}$", username): | |
print( | |
"Invalid username. Usernames must be lowercase a-z, 0-9, from 3 to 16 characters long, and cannot start with a number." | |
) | |
password = getpass.getpass(prompt="Enter your password: ") | |
if not db.get("user." + username, default=None): | |
confirm_password = getpass.getpass(prompt="Confirm your password: ") | |
if password == confirm_password: | |
hashed_password = bcrypt.hashpw(password.encode(), bcrypt.gensalt()) | |
user = User(username, hashed_password.decode(), | |
datetime.datetime.utcnow(), datetime.datetime.utcnow(), | |
datetime.datetime.utcnow()) | |
db.set(f'user.{username}', json.dumps(user.to_dict())) | |
print(f"Welcome {username}! You have been added as a new user.") | |
else: | |
print("Passwords do not match. Please try again.") | |
continue | |
else: | |
user = json.loads(db.get(f'user.{username}'), | |
object_hook=User.from_dict) | |
if bcrypt.checkpw(password.encode(), user.password_hash.encode()): | |
print(f"Welcome back {username}!") | |
else: | |
print("Incorrect password. Please try again.") | |
continue | |
self.username = username | |
self.main() | |
self.username = None | |
def main(self): | |
while not self.is_exiting: | |
print("") | |
activity, *args = input(f"{self.username}> ").strip().split() or ("", ) | |
if not activity.strip(): | |
continue | |
for action, handler in self.action_handlers.items(): | |
if action.startswith(activity): | |
handler(*args) | |
break | |
else: | |
print("Invalid action. Enter `help` for valid actions.") | |
def _reset(self, *args, **kwargs): | |
db.clear() | |
self.is_exiting = True | |
print("All users removed.") | |
def _users_list(self, *args, **kwargs): | |
for user in db.prefix("user."): | |
print(re.sub(r"^user[.]", "", user)) | |
continue | |
def _exit_game(self, *args, **kwargs): | |
self.is_exiting = True | |
def _help(self, *args, **kwargs): | |
print("Valid actions") | |
actions_list = ", ".join(self.action_handlers.keys()) | |
print("\t" + actions_list if actions_list else "(none)") | |
def _user_id(self, *args, **kwargs): | |
if args and not db.get(f'user.{args[0]}', default=None): | |
print("Unknown username.") | |
return | |
user = json.loads(db.get(f'user.{args[0] if args else self.username}'), | |
object_hook=User.from_dict) | |
print(user) | |
if __name__ == "__main__": | |
if not db: | |
print("You need to be signed in to replit.com to use this app.") | |
print("The data you persist will only be visible to your account.") | |
exit(1) | |
game = Game() | |
game.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment