This commit is contained in:
muchwowmining 2022-03-12 12:23:22 +01:00 committed by dsc
commit 6b300fd304
22 changed files with 1082 additions and 0 deletions

5
TODO Normal file
View file

@ -0,0 +1,5 @@
remove Constraints.client_secret before publishing and make a backup of it!!
Register new application new login.wownero.com
client_id = yellwowpages
client url = <domain>/authenticate

0
classes/__init__.py Normal file
View file

8
classes/constraints.py Normal file
View file

@ -0,0 +1,8 @@
from starlette.templating import Jinja2Templates
class Constraints:
templates = Jinja2Templates(directory='frontend/templates')
client_id = ''
client_secret = ''
uri = 'sqlite:///users.db'

View file

@ -0,0 +1,4 @@
:root{
--yellow: #ffcc00;
--purple: #ff2ad4;
}

1
frontend/static/icon.css Normal file

File diff suppressed because one or more lines are too long

BIN
frontend/static/wownero.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>YellWOWPages - Sex and Drugs in the metaverse</title>
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
<link rel="stylesheet" href="../../static/colors.css">
<link rel="stylesheet" href="../../static/icon.css">
</head>
<style>
html, body{
font-family: 'Courier New', Courier, monospace;
overflow: hidden;
}
a{
color: var(--yellow);
}
span{
color: var(--purple);
}
.nav{
border-color: var(--yellow);
border: 2px;
}
#dropdown{
position: relative;
display: inline-block;
}
#dropdowncontent{
display: none;
top: 0;
position: absolute;
background-color: var(--table-border-color);
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
padding: 30px 50px;
color: var(--yellow);
text-align: center;
z-index: 1;
}
#dropdown:hover #dropdowncontent {
display: block;
}
#main{
width: 100%;
height: 80vh;
display: grid;
place-content: center;
text-align: center;
}
form{
height: 50px;
}
#footer{
height: 12vh;
width: 100%;
text-align: center;
}
@media (max-width: 800px) {
kbd{
width: 100vw;
}
}
</style>
<body>
<div class="container-fluid">
<nav>
<ul>
<li>
<div id="dropdown">
<i class="icon icon-menu"></i>
<div id="dropdowncontent">
<p>
<a href="/login">Login</a>
<a href="/dashboard">Dashboard</a>
<a href="/yellwowpage">Yell<span>WOW</span>Page</a>
<a href="/about">About</a>
<a href="/about/api">Api</a>
</p>
</div>
</div>
</li>
</ul>
<ul>
<li><strong><a href="/">Yell<span>WOW</span>Pages</a></strong></li>
</ul>
<ul>
<li><a href="https://git.wownero.com/muchwowmining/YellWOWPages"><i class="icon icon-edit"></i></a></li>
</ul>
</nav>
</div>
<div class="container-fluid">
<div id="main">
<h1>About - Api</h1>
<p>
Search user: <code><a href="/api/user/{username}" data-tooltip="no partial search yet">/api/user/{username}</a></code>
<br><br>
Get all users: <code><a href="/api/all">/api/all</a></code>
</p>
</div>
</div>
<div id="footer">
2022 - ... [the future is w0w]
</div>
</body>
</html>

View file

@ -0,0 +1,125 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>YellWOWPages - Sex and Drugs in the metaverse</title>
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
<link rel="stylesheet" href="../../static/colors.css">
<link rel="stylesheet" href="../../static/icon.css">
</head>
<style>
html, body{
font-family: 'Courier New', Courier, monospace;
overflow: hidden;
}
a{
color: var(--yellow);
}
span{
color: var(--purple);
}
.nav{
border-color: var(--yellow);
border: 2px;
}
#dropdown{
position: relative;
display: inline-block;
}
#dropdowncontent{
display: none;
top: 0;
position: absolute;
background-color: var(--table-border-color);
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
padding: 30px 50px;
color: var(--yellow);
text-align: center;
z-index: 1;
}
#dropdown:hover #dropdowncontent {
display: block;
}
#main{
width: 100%;
height: 80vh;
display: grid;
place-content: center;
text-align: center;
}
form{
height: 50px;
}
#footer{
height: 12vh;
width: 100%;
text-align: center;
}
@media (max-width: 800px) {
kbd{
width: 100vw;
}
}
</style>
<body>
<div class="container-fluid">
<nav>
<ul>
<li>
<div id="dropdown">
<i class="icon icon-menu"></i>
<div id="dropdowncontent">
<p>
<a href="/login">Login</a>
<a href="/dashboard">Dashboard</a>
<a href="/yellwowpage">Yell<span>WOW</span>Page</a>
<a href="/about">About</a>
<a href="/about/api">Api</a>
</p>
</div>
</div>
</li>
</ul>
<ul>
<li><strong><a href="/">Yell<span>WOW</span>Pages</a></strong></li>
</ul>
<ul>
<li><a href="https://git.wownero.com/muchwowmining/YellWOWPages"><i class="icon icon-edit"></i></a></li>
</ul>
</nav>
</div>
<div class="container-fluid">
<div id="main">
<h1>About</h1>
<p>
Search for any Wownero <em>sub-address</em> you want by username and pay
the world!
<br>
This application uses <u>Wownero's Centralized Authentication Service.</u>
</p>
<p>
Other Wownero related stuff:
<br>
<a href="https://wownero.org/">WebSite</a>
<br>
<a href="https://suchwow.xyz">SuchWow</a>
<br>
<a href="https://git.wownero.com">Official Git</a>
<br>
<a href="https://discord.com/invite/ykZyAzJhDK">Discord server</a>
</p>
<p>
Idea of: dsc_
<br>
Made by <a href="https://notmtth.xyz">NotMtth</a>
</p>
</div>
</div>
<div id="footer">
2022 - ... [the future is w0w]
</div>
</body>
</html>

View file

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Such dashboard</title>
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
<link rel="stylesheet" href="../../static/colors.css">
<link rel="stylesheet" href="../../static/icon.css">
</head>
<style>
html, body{
font-family: 'Courier New', Courier, monospace;
overflow: hidden;
}
a{
color: var(--yellow);
}
span{
color: var(--purple);
}
.nav{
border-color: var(--yellow);
border: 2px;
}
#dropdown{
position: relative;
display: inline-block;
}
#dropdowncontent{
display: none;
top: 0;
position: absolute;
background-color: var(--table-border-color);
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
padding: 30px 50px;
color: var(--yellow);
text-align: center;
z-index: 1;
}
#dropdown:hover #dropdowncontent {
display: block;
}
#main{
width: 100%;
height: 85vh;
display: grid;
place-content: center;
}
@media (max-width: 800px) {}
</style>
<body>
<div class="container-fluid">
<nav>
<ul>
<li>
<div id="dropdown">
<i class="icon icon-menu"></i>
<div id="dropdowncontent">
<p>
<a href="/login">Login</a>
<a href="/dashboard">Dashboard</a>
<a href="/yellwowpage">Yell<span>WOW</span>Page</a>
<a href="/about">About</a>
<a href="/about/api">Api</a>
</p>
</div>
</div>
</li>
</ul>
<ul>
<li><strong><a href="/">Yell<span>WOW</span>Pages</a></strong></li>
</ul>
<ul>
<li><a href="https://git.wownero.com/muchwowmining/YellWOWPages"><i class="icon icon-edit"></i></a></li>
</ul>
</nav>
</div>
<div class="container-fluid">
<div id="main">
<article>
{% for username, address in user_data.items() %}
<Header>Welcome back <em>{{username}}</em>!</Header>
Current <u>sub-address</u>: <label><mark>{{address}}</mark></label>
<footer>
Change <u>sub-address</u>:
<form action="/submit_address" method="POST">
<input type="text" name="address">
<button data-tooltip="Be sure it's correct">Submit</button>
</form>
</footer>
{% endfor %}
</article>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="refresh" content="3; URL={{url}}">
<title>Such error :(</title>
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
<link rel="stylesheet" href="../../static/colors.css">
<link rel="stylesheet" href="../../static/icon.css">
</head>
<style>
html, body{
font-family: 'Courier New', Courier, monospace;
}
#main{
height: 100vh;
display: grid;
place-content: center;
}
</style>
<body>
<div class="container-fluid">
<div id="main">
<p>Error: {{error}}</p>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>YellWOWPages - Sex and Drugs in the metaverse</title>
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
<link rel="stylesheet" href="../../static/colors.css">
<link rel="stylesheet" href="../../static/icon.css">
</head>
<style>
html, body{
font-family: 'Courier New', Courier, monospace;
overflow-x: hidden;
}
a{
color: var(--yellow);
}
span{
color: var(--purple);
}
strong{
color: var(--yellow);
}
#dropdown{
position: relative;
display: inline-block;
}
#dropdowncontent{
display: none;
top: 0;
position: absolute;
background-color: var(--table-border-color);
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
padding: 30px 50px;
color: var(--yellow);
text-align: center;
z-index: 1;
}
#dropdown:hover #dropdowncontent {
display: block;
}
#main{
width: 100%;
height: 80vh;
display: grid;
place-content: center;
}
main{
font-size: bold;
font-size: 10rem;
}
img{
width: 50px;
height: 50px;
object-fit: contain;
}
#footer{
height: 12vh;
width: 100%;
text-align: center;
}
@media (max-width: 800px) {
main{
font-size: 4rem;
}
}
</style>
<body>
<div class="container-fluid">
<nav>
<ul>
<li>
<div id="dropdown">
<i class="icon icon-menu"></i>
<div id="dropdowncontent">
<p>
<a href="/login">Login</a>
<a href="/dashboard">Dashboard</a>
<a href="/yellwowpage">Yell<span>WOW</span>Page</a>
<a href="/about">About</a>
<a href="/about/api">Api</a>
</p>
</div>
</div>
</li>
</ul>
<ul>
<li><a href="https://git.wownero.com/muchwowmining/YellWOWPages"><i class="icon icon-edit"></i></a></li>
</ul>
</nav>
</div>
<div class="container-fluid">
<div id="main">
<main>
<strong>Yell<span>WOW</span>Pages</strong>
</main>
<div>
The first <img src="../../static/wownero.png" alt=""> addresses library -
from the community to the community
</div>
</div>
</div>
<div id="footer">
2022 - ... [the future is w0w]
</div>
</body>
</html>

View file

@ -0,0 +1,126 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>YellWOWPages - Sex and Drugs in the metaverse</title>
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
<link rel="stylesheet" href="../../static/colors.css">
<link rel="stylesheet" href="../../static/icon.css">
</head>
<style>
html, body{
font-family: 'Courier New', Courier, monospace;
overflow-x: hidden;
}
a{
color: var(--yellow);
}
span{
color: var(--purple);
}
.nav{
border-color: var(--yellow);
border: 2px;
}
#dropdown{
position: relative;
display: inline-block;
}
#dropdowncontent{
display: none;
top: 0;
position: absolute;
background-color: var(--table-border-color);
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
padding: 30px 50px;
color: var(--yellow);
text-align: center;
z-index: 1;
}
#dropdown:hover #dropdowncontent {
display: block;
}
#main{
width: 100%;
height: 80vh;
display: grid;
place-content: center;
}
form{
height: 80px;
}
#addresses{
width: 100%;
height: 50vh;
overflow-y: auto;
}
#addresses::-webkit-scrollbar{
display: none;
}
#footer{
height: 12vh;
width: 100%;
text-align: center;
}
@media (max-width: 800px) {
kbd{
width: 100vw;
}
}
</style>
<body>
<div class="container-fluid">
<nav>
<ul>
<li>
<div id="dropdown">
<i class="icon icon-menu"></i>
<div id="dropdowncontent">
<p>
<a href="/login">Login</a>
<a href="/dashboard">Dashboard</a>
<a href="/yellwowpage">Yell<span>WOW</span>Page</a>
<a href="/about">About</a>
<a href="/about/api">Api</a>
</p>
</div>
</div>
</li>
</ul>
<ul>
<li><strong><a href="/">Yell<span>WOW</span>Pages</a></strong></li>
</ul>
<ul>
<li><a href="https://git.wownero.com/muchwowmining/YellWOWPages"><i class="icon icon-edit"></i></a></li>
</ul>
</nav>
</div>
<div class="container-fluid">
<div id="main">
<form action="/search" method="GET">
<input type="text" name="username" placeholder="Username to search">
<label for="switch">
<input type="checkbox" name="switch" role="switch">
<em data-tooltip="Search address with a part of username; get 3 results">Partial</em>
</label>
</form>
<div id="addresses">
{% for username, address in user_data.items() %}
<article>
<header>
<em>{{username}}</em>
</header>
<kbd>{{address}}</kbd>
</article>
{% endfor %}
</div>
</div>
</div>
<div id="footer">
2022 - ... [the future is w0w]
</div>
</body>
</html>

View file

@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>YellWOWPages - Sex and Drugs in the metaverse</title>
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
<link rel="stylesheet" href="../../static/colors.css">
<link rel="stylesheet" href="../../static/icon.css">
</head>
<style>
html, body{
font-family: 'Courier New', Courier, monospace;
overflow: hidden;
}
a{
color: var(--yellow);
}
span{
color: var(--purple);
}
.nav{
border-color: var(--yellow);
border: 2px;
}
#dropdown{
position: relative;
display: inline-block;
}
#dropdowncontent{
display: none;
top: 0;
position: absolute;
background-color: var(--table-border-color);
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
padding: 30px 50px;
color: var(--yellow);
text-align: center;
z-index: 1;
}
#dropdown:hover #dropdowncontent {
display: block;
}
#main{
width: 100%;
height: 80vh;
display: grid;
place-content: center;
}
form{
height: 80px;
}
#addresses{
width: 100%;
height: 50vh;
overflow-y: auto;
}
#addresses::-webkit-scrollbar{
display: none;
}
#footer{
height: 12vh;
width: 100%;
text-align: center;
}
@media (max-width: 800px) {
kbd{
width: 100vw;
}
}
</style>
<body>
<div class="container-fluid">
<nav>
<ul>
<li>
<div id="dropdown">
<i class="icon icon-menu"></i>
<div id="dropdowncontent">
<p>
<a href="/login">Login</a>
<a href="/dashboard">Dashboard</a>
<a href="/yellwowpage">Yell<span>WOW</span>Page</a>
<a href="/about">About</a>
<a href="/about/api">Api</a>
</p>
</div>
</div>
</li>
</ul>
<ul>
<li><strong><a href="/">Yell<span>WOW</span>Pages</a></strong></li>
</ul>
<ul>
<li><a href="https://git.wownero.com/muchwowmining/YellWOWPages"><i class="icon icon-edit"></i></a></li>
</ul>
</nav>
</div>
<div class="container-fluid">
<div id="main">
<form action="/search" method="GET">
<input type="text" name="username" placeholder="Username to search">
<label for="switch">
<input type="checkbox" name="switch" role="switch">
<em data-tooltip="Search address with a part of username; get 3 results">Partial</em>
</label>
</form>
<br>
Result: {{user_data|length}}
{% if not user_data|length %}
Nothing found...
{% else %}
<div id="addresses">
{% for username, address in user_data.items() %}
<article>
<header>
<em>{{username}}</em>
</header>
<kbd>{{address}}</kbd>
</article>
{% endfor %}
</div>
{% endif %}
</div>
</div>
<div id="footer">
2022 - ... [the future is w0w]
</div>
</body>
</html>

45
main.py Normal file
View file

@ -0,0 +1,45 @@
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
import uvicorn
from classes.constraints import Constraints
from starlette.exceptions import HTTPException as StarletteHTTPException
app = FastAPI(docs_url=None, redoc_url=None)
app.mount('/static', StaticFiles(directory='frontend/static'), name='static')
from routers import auth, static, dashboard, db, api
app.include_router(auth.router)
app.include_router(dashboard.router)
app.include_router(static.router)
app.include_router(api.router)
@app.get("/")
@app.get('/root', response_class=HTMLResponse)
async def root(request: Request):
return Constraints.templates.TemplateResponse('/root/index.html', {'request': request})
# shitty error handling
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
if exc.status_code == 404:
return Constraints.templates.TemplateResponse('/errors/index.html', {'request': request,
'error': 'not found...',
'url': '/root'})
elif exc.status_code == 500:
return Constraints.templates.TemplateResponse('/errors/index.html', {'request': request,
'error': 'internal server error',
'url': '/root'})
return Constraints.templates.TemplateResponse('/errors/index.html', {'request': request,
'error': exc.detail,
'url': '/root'})
if __name__ == '__main__':
uvicorn.run(app, host='127.0.0.1', port=8080)

30
requirements.txt Normal file
View file

@ -0,0 +1,30 @@
anyio==3.5.0
asgiref==3.5.0
asttokens==2.0.5
certifi==2021.10.8
charset-normalizer==2.0.12
click==8.0.4
colorama==0.4.4
executing==0.8.3
fastapi==0.75.0
Flask==2.0.3
Flask-SQLAlchemy==2.5.1
greenlet==1.1.2
h11==0.13.0
icecream==2.1.2
idna==3.3
itsdangerous==2.1.1
Jinja2==3.0.3
MarkupSafe==2.1.0
pydantic==1.9.0
Pygments==2.11.2
python-multipart==0.0.5
requests==2.27.1
six==1.16.0
sniffio==1.2.0
SQLAlchemy==1.4.32
starlette==0.17.1
typing-extensions==4.1.1
urllib3==1.26.8
uvicorn==0.17.5
Werkzeug==2.0.3

0
routers/__init__.py Normal file
View file

32
routers/api.py Normal file
View file

@ -0,0 +1,32 @@
from fastapi import APIRouter, Request, Form
from fastapi.responses import RedirectResponse, HTMLResponse
from icecream import ic
from classes.constraints import Constraints
from .db import Database
router = APIRouter()
# external api
@router.get('/api/user/{username}')
async def get_api(request: Request, username: str):
if not Database.Users.get_address(username):
return {'error': 'invalid user'}
return Database.Users.get_address(username)
@router.get('/api/all')
async def get_api_all(request: Request):
return Database.Users.get_all()
# site search redirect
@router.get('/search')
async def search_api(request: Request):
username = request.query_params['username']
ic(request.query_params.get('switch', None) == 'on')
if request.query_params.get('switch', None) == 'on':
return RedirectResponse(f'/yellwowpage/matches/{username}')
else:
return RedirectResponse(f'/yellwowpage/user/{username}')

68
routers/auth.py Normal file
View file

@ -0,0 +1,68 @@
from fastapi import APIRouter, Request, Cookie
from fastapi.responses import RedirectResponse, HTMLResponse
import requests
from icecream import ic
import secrets
from classes.constraints import Constraints
router = APIRouter()
@router.get('/login')
async def get_login(request: Request):
state = secrets.token_hex(10)
response = RedirectResponse(
'https://login.wownero.com/auth/realms/master/protocol/openid-connect/auth?'f'client_id='
f'{Constraints.client_id}&redirect_uri=https://yellow.wownero.com/authenticate&'
f'response_type=code&state={state}')
response.set_cookie(key='state', value=state)
return response
@router.get('/authenticate')
async def get_auth(request: Request, state: str = Cookie(None)):
params = request.query_params
if state is None:
return Constraints.templates.TemplateResponse('/errors/index.html',
{'request': request,
'error': '`state` security code not found...',
'url': '/login'})
if params['state'] != state:
return Constraints.templates.TemplateResponse('/errors/index.html',
{'request': request,
'error': '`state` security code is wrong',
'url': '/login'})
url = "https://login.wownero.com/auth/realms/master/protocol/openid-connect/token"
data = {
"grant_type": "authorization_code",
"code": params["code"],
"redirect_uri": "http://127.0.0.1:8080/authenticate",
"client_id": f'{Constraints.client_id}',
"client_secret": f'{Constraints.client_secret}',
"state": params['state']
}
r = requests.post(url=url, data=data)
response = r.json()
if response.get('error', None) is not None:
return Constraints.templates.TemplateResponse('/errors/index.html',
{'request': request, 'error': r.json()['error_description'],
'url': '/login'})
auth_code = response.get('access_token', None)
if auth_code is None:
return Constraints.templates.TemplateResponse('/errors/index.html',
{'request': request, 'error': 'invalid auth code',
'url': '/login'})
response = RedirectResponse('/dashboard')
response.set_cookie(key='auth_code', value=auth_code)
response.delete_cookie(key='state')
return response
@router.get('/logout')
async def get_logout():
response = RedirectResponse('/root')
response.delete_cookie('auth_code')
return response

63
routers/dashboard.py Normal file
View file

@ -0,0 +1,63 @@
from fastapi import APIRouter, Request, Cookie, Form
from fastapi.responses import RedirectResponse, HTMLResponse
import requests
from icecream import ic
from classes.constraints import Constraints
from .db import Database
router = APIRouter()
@router.get('/dashboard', response_class=HTMLResponse)
async def get_dashboard(request: Request, auth_code: str = Cookie(None)):
if auth_code is None:
return Constraints.templates.TemplateResponse('/errors/index.html', {'request': request,
'error': 'not logged in',
'url': '/login'})
url = "https://login.wownero.com/auth/realms/master/protocol/openid-connect/userinfo"
response = requests.post(url, headers={"Authorization": f"Bearer {auth_code}"})
user_profile = response.json()
if user_profile.get('preferred_username', None) is None:
return Constraints.templates.TemplateResponse('/errors/index.html', {'request': request,
'error': 'account not found...',
'url': '/login'})
user_name = user_profile.get('preferred_username', None)
return Constraints.templates.TemplateResponse('/dashboard/index.html', {'request': request,
'user_data': Database.Users.get_address(user_name)})
@router.post('/submit_address')
async def post_submit_address(request: Request, auth_code: str = Cookie(None), address: str = Form(None)):
if auth_code is None:
return Constraints.templates.TemplateResponse('/errors/index.html', {'request': request,
'error': 'not logged in',
'url': '/login'})
if address is None:
return Constraints.templates.TemplateResponse('/errors/index.html', {'request': request,
'error': 'invalid address',
'url': '/dashboard'})
if len(address) != 97:
return Constraints.templates.TemplateResponse('/errors/index.html', {'request': request,
'error': 'invalid address length',
'url': '/dashboard'})
url = "https://login.wownero.com/auth/realms/master/protocol/openid-connect/userinfo"
response = requests.post(url, headers={"Authorization": f"Bearer {auth_code}"})
user_name = response.json().get('preferred_username', None)
if not Database.Users.get_address(user_name):
new_user = Database.Users(username=user_name, address=address)
Database.sqla.session.add(new_user)
Database.sqla.session.commit()
return RedirectResponse('/dashboard', status_code=303)
update_address = Database.Users.query.filter_by(username=user_name).first()
update_address.address = address
Database.sqla.session.commit()
return RedirectResponse('/dashboard', status_code=303)

54
routers/db.py Normal file
View file

@ -0,0 +1,54 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from icecream import install, ic
from classes.constraints import Constraints
app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = Constraints.uri
db = SQLAlchemy(app, session_options={'autocommit': False})
class Users(db.Model):
__tablename__ = 'wowusers'
username = db.Column(db.VARCHAR(32), primary_key=True)
address = db.Column(db.CHAR(97), nullable=False)
@staticmethod
def get_address(username):
user_data = {}
try:
user_data.update({Users.query.filter_by(username=username).first().username:
Users.query.filter_by(username=username).first().address})
except AttributeError:
return user_data
return user_data
@staticmethod
def get_all():
users_data = {}
for user in Users.query.all():
users_data.update({user.username: user.address})
return users_data
@staticmethod
def get_matches(username):
user_data = {}
try:
for i in range(3):
user = Users.query.filter(Database.Users.username.like(f'%{username}%'))[i]
user_data.update({user.username: user.address})
except IndexError:
return user_data
return user_data
class Database:
Users = Users
sqla = db
db.create_all()
ic('db done')

2
routers/errors.py Normal file
View file

@ -0,0 +1,2 @@
# stupid fastapi error handling drove me crazy for some hours, updating this asap
# the handler is in the main file

39
routers/static.py Normal file
View file

@ -0,0 +1,39 @@
from fastapi import APIRouter, Request
from fastapi.responses import RedirectResponse, HTMLResponse
from icecream import ic
from classes.constraints import Constraints
from .db import Database
router = APIRouter()
@router.get('/yellwowpage')
async def get_yellwowpage(request: Request):
return Constraints.templates.TemplateResponse('/yellwow/index.html',
{'request': request, 'user_data': Database.Users.get_all()})
@router.get('/yellwowpage/user/{username}')
async def get_yellwowpage(request: Request, username: str):
return Constraints.templates.TemplateResponse('/yellwow/single_user/index.html',
{'request': request,
'user_data': Database.Users.get_address(username)})
@router.get('/yellwowpage/matches/{username}')
async def get_yellwowpage_matches(request: Request, username: str):
ic(Database.Users.get_matches(username))
return Constraints.templates.TemplateResponse('/yellwow/single_user/index.html',
{'request': request,
'user_data': Database.Users.get_matches(username)})
@router.get('/about')
async def get_about(request: Request):
return Constraints.templates.TemplateResponse('/about/index.html', {'request': request})
@router.get('/about/api')
async def get_api_about(request: Request):
return Constraints.templates.TemplateResponse('/about/api/index.html', {'request': request})