those are some haxxor moments
This commit is contained in:
1 parent
88d4ce7320
commit
a8e5c26d55
7 files changed
+935
-330
No files matched your search
@@ -0,0 +1,4 @@
|
|||||||
|
db_user = user
|
||||||
|
db_password = pa55w0rd
|
||||||
|
db_host = 127..1
|
||||||
|
db_name = database
|
||||||
+11
-1
@@ -8,13 +8,21 @@ import http.server as serverhttp
|
|||||||
from the_server_handler import ServerLogic, connectionSettings, get_that_connection
|
from the_server_handler import ServerLogic, connectionSettings, get_that_connection
|
||||||
import mysql.connector as sqlcon
|
import mysql.connector as sqlcon
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if not (
|
||||||
|
sys.version_info.major > 3
|
||||||
|
or (sys.version_info.major == 3 and sys.version_info.minor >= 11)
|
||||||
|
):
|
||||||
|
raise Exception(f"python 3.11 up, u running {sys.version}")
|
||||||
|
|
||||||
|
PORT = 8088
|
||||||
def runServer():
|
def runServer():
|
||||||
# while True:
|
# while True:
|
||||||
# connectio,e = get_that_connection(**connectionSettings)
|
# connectio,e = get_that_connection(**connectionSettings)
|
||||||
# if not e:
|
# if not e:
|
||||||
# break
|
# break
|
||||||
server = serverhttp.HTTPServer(("", 8088), ServerLogic)
|
server = serverhttp.HTTPServer(("", PORT), ServerLogic)
|
||||||
try:
|
try:
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
@@ -23,6 +31,8 @@ def runServer():
|
|||||||
raise SystemExit("\nctrl c")
|
raise SystemExit("\nctrl c")
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
# finally:
|
||||||
|
# print("why am i printing")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
+644
-280
@@ -1,19 +1,41 @@
|
|||||||
import http.server as serverhttp
|
import http.server as serverhttp
|
||||||
import mysql.connector as sqlcon
|
import warnings
|
||||||
from dotenv import dotenv_values
|
|
||||||
import json
|
|
||||||
# import urllib, sql
|
|
||||||
|
|
||||||
|
# import chardet
|
||||||
|
from http import HTTPStatus as rescode
|
||||||
|
import mimetypes
|
||||||
|
|
||||||
|
# import traceback
|
||||||
|
import os
|
||||||
|
from typing import Literal
|
||||||
|
import mysql.connector as sqlcon
|
||||||
|
|
||||||
|
# from mysql.connector import errorcode
|
||||||
|
from dotenv import dotenv_values
|
||||||
|
from urllib import parse as urlparse # lmao the normal person
|
||||||
|
import json
|
||||||
|
from functools import wraps
|
||||||
|
from pathlib import Path
|
||||||
|
from dotenv import dotenv_values
|
||||||
|
|
||||||
|
|
||||||
|
# import urllib, sql
|
||||||
|
class ServerLogic(serverhttp.BaseHTTPRequestHandler): ...
|
||||||
|
|
||||||
|
|
||||||
|
webrootdir = "webRoot"
|
||||||
|
if os.path.isdir(webrootdir): # unfuckable
|
||||||
|
os.chdir(webrootdir) # move to safe part of world
|
||||||
|
curdir = os.path.curdir or os.getcwd()
|
||||||
|
print(os.path.curdir, os.getcwd())
|
||||||
from things import (
|
from things import (
|
||||||
|
process_datetime_DICTS,
|
||||||
process_datetime_tuples,
|
process_datetime_tuples,
|
||||||
funny_tuples_to_dicts_processor,
|
funny_tuples_to_dicts_processor,
|
||||||
getnewdicttranslate,
|
getnewdicttranslate,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dotenv_values1 = dotenv_values() ## change so fast
|
||||||
from dotenv import dotenv_values
|
|
||||||
|
|
||||||
dotenv_values1 = dotenv_values() ## change so fast
|
|
||||||
db_name = dotenv_values1["db_name"]
|
db_name = dotenv_values1["db_name"]
|
||||||
|
|
||||||
comectomKeys = ["user", "password", "host", "database"]
|
comectomKeys = ["user", "password", "host", "database"]
|
||||||
@@ -26,6 +48,8 @@ comectomtrk = {
|
|||||||
connectionSettings = {
|
connectionSettings = {
|
||||||
**getnewdicttranslate(dotenv_values1, comectomtrk),
|
**getnewdicttranslate(dotenv_values1, comectomtrk),
|
||||||
"raise_on_warnings": True,
|
"raise_on_warnings": True,
|
||||||
|
"pool_name": "aPool", # wow!
|
||||||
|
"pool_size": 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -40,18 +64,251 @@ def get_that_connection(
|
|||||||
return (connectio, None)
|
return (connectio, None)
|
||||||
|
|
||||||
|
|
||||||
|
def better_connection_actuallyworking(connectionSettings: dict):
|
||||||
|
"""
|
||||||
|
arg for func:
|
||||||
|
1. conn (do you hate life)
|
||||||
|
2. thingElse
|
||||||
|
"""
|
||||||
|
|
||||||
|
def ONETHING(func):
|
||||||
|
@wraps(func)
|
||||||
|
def huh(*a, **kw):
|
||||||
|
# conn = sqlcon.connect(**connectionSettings)
|
||||||
|
try:
|
||||||
|
with sqlcon.connect(
|
||||||
|
**connectionSettings
|
||||||
|
) as conn: # HOLY SHIT THANK YOU CHAT GPT
|
||||||
|
return func(conn, *a, **kw)
|
||||||
|
except sqlcon.Error as e:
|
||||||
|
print("oh hey errorSql FromtheWrapper", e)
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
print("betterConnection NoWorked", e)
|
||||||
|
raise e
|
||||||
|
# finally: # they run even after return! try finally gon go crazy
|
||||||
|
# conn.close()
|
||||||
|
|
||||||
|
return huh
|
||||||
|
|
||||||
|
return ONETHING
|
||||||
|
|
||||||
|
|
||||||
|
@better_connection_actuallyworking(connectionSettings)
|
||||||
|
def funnying_funnytheFunnier(
|
||||||
|
conn: sqlcon.MySQLConnection | sqlcon.pooling.PooledMySQLConnection,
|
||||||
|
):
|
||||||
|
return conn # WHAT NOT TO DO
|
||||||
|
|
||||||
|
|
||||||
|
# if __name__ == "__main__":
|
||||||
|
# conn = funnying_funnytheFunnier()
|
||||||
|
# print(f"Connection object: {conn}")
|
||||||
|
# print(f"Internal connection (_cnx): {getattr(conn, '_cnx', 'Not available')}")
|
||||||
|
# try:
|
||||||
|
# with conn.cursor() as cur:
|
||||||
|
# cur.execute('SELECT "Hello world"')
|
||||||
|
# print(cur.fetchall())
|
||||||
|
# except Exception as e:
|
||||||
|
# traceback.print_exc()
|
||||||
|
# if __name__ == "__main__":
|
||||||
|
# print("a separator")
|
||||||
|
# with sqlcon.connect( pool_name = "ig", **connectionSettings) as conn:
|
||||||
|
# print(f"Connection object: {conn}")
|
||||||
|
# print(f"Internal connection (_cnx): {getattr(conn, '_cnx', 'Not available')}")
|
||||||
|
# with conn.cursor() as cur:
|
||||||
|
# cur.execute('SELECT "Hello world!~"') #gayà
|
||||||
|
# print(cur.fetchall())
|
||||||
|
|
||||||
|
|
||||||
|
@better_connection_actuallyworking(connectionSettings)
|
||||||
|
def fulltable(
|
||||||
|
conn: sqlcon.MySQLConnection | sqlcon.pooling.PooledMySQLConnection,
|
||||||
|
tbaleName: str,
|
||||||
|
returnType: Literal["zip", "dict"] = "dict",
|
||||||
|
) -> dict | tuple[list[tuple], list[str]]: # connection is inserted in by the thing
|
||||||
|
print(tbaleName)
|
||||||
|
if not (tableName := ifTableInDB(db_name, tbaleName)):
|
||||||
|
raise sqlcon.DatabaseError(f"{tbaleName} where tELL ME")
|
||||||
|
ifdict = returnType == "dict"
|
||||||
|
try:
|
||||||
|
with conn.cursor(dictionary=ifdict, prepared=True) as cur:
|
||||||
|
res = cur.execute(f"select * from {tableName}")
|
||||||
|
r = cur.fetchall()
|
||||||
|
if ifdict:
|
||||||
|
return r
|
||||||
|
this = getColumename(tableName)
|
||||||
|
return this, r
|
||||||
|
except sqlcon.Error as e:
|
||||||
|
print("table has a", e)
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
print("Hi. Your except saved yo ass:", e)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
@better_connection_actuallyworking(connectionSettings)
|
||||||
|
def getColumename(
|
||||||
|
conn: sqlcon.MySQLConnection | sqlcon.pooling.PooledMySQLConnection, tbaleName: str
|
||||||
|
) -> list[str]:
|
||||||
|
print(tbaleName)
|
||||||
|
try:
|
||||||
|
with conn.cursor(prepared=True) as cur:
|
||||||
|
res = cur.execute(
|
||||||
|
"select column_name from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = ?",
|
||||||
|
(tbaleName,),
|
||||||
|
)
|
||||||
|
coln = cur.fetchall()
|
||||||
|
for a, i in enumerate(coln):
|
||||||
|
coln[a] = i[0]
|
||||||
|
return coln
|
||||||
|
except sqlcon.Error as e:
|
||||||
|
print("getColumename has a", e)
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
print("Hi. Your except saved yo ass:", e)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
@better_connection_actuallyworking(connectionSettings)
|
||||||
|
def getTableNmaes(
|
||||||
|
conn: sqlcon.MySQLConnection | sqlcon.pooling.PooledMySQLConnection, db_name: str
|
||||||
|
) -> list[str]:
|
||||||
|
try:
|
||||||
|
with conn.cursor(prepared=True) as cur:
|
||||||
|
res = cur.execute(
|
||||||
|
"select table_name from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = ?",
|
||||||
|
(db_name,),
|
||||||
|
)
|
||||||
|
coln = cur.fetchall()
|
||||||
|
for a, i in enumerate(coln):
|
||||||
|
coln[a] = i[0]
|
||||||
|
return coln
|
||||||
|
except sqlcon.Error as e:
|
||||||
|
print("getTableNmaes has a", e)
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
print("Hi. Your except saved yo ass:", e)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
tableNamesListsth: list = getTableNmaes(db_name)
|
||||||
|
tabletbale = "tbale" if "tbale" in tableNamesListsth else None ## hard Coding
|
||||||
|
colnmaes = getColumename(tabletbale)
|
||||||
|
# {"neme": "one", "kewod": "two", "cod": "three", "expi": "four"}
|
||||||
|
severColum = ["neme", "kewod", "cod", "expi"]
|
||||||
|
clietColum = ["one", "two", "three", "four"]
|
||||||
|
scTrtb = dict(zip(severColum, clietColum))
|
||||||
|
csTrtb = dict(zip(clietColum, severColum))
|
||||||
|
print(scTrtb, csTrtb)
|
||||||
|
|
||||||
|
|
||||||
|
@better_connection_actuallyworking(connectionSettings)
|
||||||
|
def ifTableInDB(
|
||||||
|
conn: sqlcon.MySQLConnection | sqlcon.pooling.PooledMySQLConnection,
|
||||||
|
db_name: str,
|
||||||
|
tabN: str,
|
||||||
|
) -> str | None:
|
||||||
|
"""you dont believe it but it works like a true false, as python is good enough
|
||||||
|
|
||||||
|
if (vari := ifTableInDB(dbname, tablename)):"""
|
||||||
|
try:
|
||||||
|
with conn.cursor(prepared=True) as cur:
|
||||||
|
|
||||||
|
res = cur.execute(
|
||||||
|
"select table_name from information_schema.tables where table_schema = ? and table_name = ? Limit 1;",
|
||||||
|
(db_name, tabN),
|
||||||
|
)
|
||||||
|
a = cur.fetchall()
|
||||||
|
if a:
|
||||||
|
return a[0][0] # deadass dont understand why this shi weird like that
|
||||||
|
return
|
||||||
|
except sqlcon.Error as e:
|
||||||
|
print("getTableNmaes has a", e)
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
print("Hi. Your except saved yo ass:", e)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
notfound404 = b"""<h1>404</h1><p>where u at</p>"""
|
||||||
|
notallowed403 = b"""<h1>403</h1><p>tf u doin</p>"""
|
||||||
|
|
||||||
|
|
||||||
|
def openFileManually(
|
||||||
|
theGuy: ServerLogic,
|
||||||
|
webDir: str,
|
||||||
|
defaultFile: str | None = "index.html",
|
||||||
|
dir: str | None = None,
|
||||||
|
headers: dict | None = None,
|
||||||
|
rootDir: str | None = curdir,
|
||||||
|
) -> None:
|
||||||
|
print(webDir, dir, headers)
|
||||||
|
if dir:
|
||||||
|
filename = dir
|
||||||
|
else:
|
||||||
|
filename = webDir.lstrip("/")
|
||||||
|
path = Path(rootDir, filename)
|
||||||
|
print(path)
|
||||||
|
if not path.exists():
|
||||||
|
theGuy.header_setup(rescode.NOT_FOUND)
|
||||||
|
if path.is_dir():
|
||||||
|
path /= defaultFile
|
||||||
|
if not path.is_file():
|
||||||
|
theGuy.header_setup(rescode.NOT_FOUND)
|
||||||
|
theGuy.wfile.write(notfound404)
|
||||||
|
print(path)
|
||||||
|
fileMime, fileEncoding = mimetypes.guess_type(path)
|
||||||
|
print(fileMime, fileEncoding)
|
||||||
|
finalMime = fileMime
|
||||||
|
a = {}
|
||||||
|
if headers:
|
||||||
|
gay = next(
|
||||||
|
(i for i in reversed(headers) if i.casefold() == "content-type"), None
|
||||||
|
)
|
||||||
|
if gay:
|
||||||
|
print(gay, headers[gay])
|
||||||
|
headerMime = headers[gay]
|
||||||
|
if headerMime not in mimetypes.types_map.values():
|
||||||
|
warnings.warn(
|
||||||
|
f"what is {headerMime}. mimetypes say {fileMime} basically uhh you uhh do this for me please: if you dont know what it is dont include it",
|
||||||
|
UserWarning,
|
||||||
|
)
|
||||||
|
|
||||||
|
finalMime = headerMime
|
||||||
|
a["content-type"] = finalMime
|
||||||
|
headers |= a
|
||||||
|
theGuy.header_setup(headers=headers or a)
|
||||||
|
|
||||||
|
with open(path, "rb") as file:
|
||||||
|
theGuy.wfile.write(file.read())
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
## USE THE @ if you know how
|
## USE THE @ if you know how
|
||||||
|
### i surely dont know how
|
||||||
|
|
||||||
|
|
||||||
class ServerLogic(serverhttp.BaseHTTPRequestHandler):
|
class ServerLogic(serverhttp.BaseHTTPRequestHandler):
|
||||||
|
|
||||||
def youJustHaveToDoTheseStuff(self):
|
def __init__(self, *a, **kw): # AHAHHAHAHAHAHAHAHA
|
||||||
|
super().__init__(*a, **kw)
|
||||||
|
|
||||||
|
def reallyEveryTime(self) -> tuple:
|
||||||
# print("all headers:\n", self.headers)
|
# print("all headers:\n", self.headers)
|
||||||
print("the path is : ", self.path)
|
print("the path is : ", self.path)
|
||||||
print(
|
print(
|
||||||
"connected at: ",
|
"connected at: ",
|
||||||
self.headers.get("X-Forwarded-For", "directly").split(", ")[0],
|
self.headers.get("X-Forwarded-For", "directly").split(", ")[0],
|
||||||
)
|
)
|
||||||
|
print(urlparse.urlparse(self.path))
|
||||||
|
|
||||||
|
# table = 'tbale'
|
||||||
|
# print("there is no" ,table,ifTableInDB(db_name, table))
|
||||||
|
# tableli = getTableNmaes(db_name)
|
||||||
|
# print(getColumename(tableli[0])) # i know damn well
|
||||||
|
# print(fulltable(tableli[0]))
|
||||||
|
return
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
try:
|
try:
|
||||||
@@ -63,310 +320,417 @@ class ServerLogic(serverhttp.BaseHTTPRequestHandler):
|
|||||||
raise SystemExit("truly the /close")
|
raise SystemExit("truly the /close")
|
||||||
|
|
||||||
def header_setup(
|
def header_setup(
|
||||||
self, code: int = 200, headers: dict = {"Content-type": "text/html"}
|
self,
|
||||||
|
code: int | rescode = rescode.OK,
|
||||||
|
headers: dict = {"Content-type": "text/html"},
|
||||||
):
|
):
|
||||||
|
"""
|
||||||
|
code as int and headers as keyvalue pairs.
|
||||||
|
"""
|
||||||
|
|
||||||
self.send_response(code)
|
self.send_response(code)
|
||||||
if headers is not None:
|
if headers is not None:
|
||||||
for key in headers:
|
for key, value in headers.items():
|
||||||
self.send_header(key, headers[key]) # why!
|
self.send_header(key, value) # why!
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
self.youJustHaveToDoTheseStuff()
|
self.reallyEveryTime()
|
||||||
|
pathObj: urlparse.ParseResult = urlparse.urlparse(self.path)
|
||||||
|
match pathObj.path:
|
||||||
|
case "/close":
|
||||||
|
return self.close()
|
||||||
|
case a if a in (
|
||||||
|
thisATable := {
|
||||||
|
"/": {
|
||||||
|
# {"dir" : "index.html",}
|
||||||
|
},
|
||||||
|
"/index/style.css": {
|
||||||
|
# "headers": {"Content-Type": "text/css"}
|
||||||
|
},
|
||||||
|
"/index/script.js": {
|
||||||
|
"headers": {"Content-Type": "text/javascript"} # bout Stupid
|
||||||
|
},
|
||||||
|
}
|
||||||
|
):
|
||||||
|
return openFileManually(
|
||||||
|
self, a, **thisATable[a]
|
||||||
|
) # i can waste objects!!!! simple or empty dicts have same id
|
||||||
|
|
||||||
if self.path == "/close":
|
# (connectio, eror) = get_that_connection(connectionSettings)
|
||||||
return self.close()
|
# if eror:
|
||||||
|
# print("coneti eror: ", eror)
|
||||||
|
# return
|
||||||
|
# # HE. MUST. AVOID. THE. TRYCATCH
|
||||||
|
# with connectio.cursor(buffered=True) as cur:
|
||||||
|
# try:
|
||||||
|
# res = cur.execute("select * from tbale")
|
||||||
|
# w = cur.fetchall()
|
||||||
|
# res = cur.execute(
|
||||||
|
# "select column_name from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'tbale'"
|
||||||
|
# )
|
||||||
|
# anotherone2 = cur.fetchall()
|
||||||
|
# except Exception as e:
|
||||||
|
# print(e)
|
||||||
|
# return # return ealy no else
|
||||||
|
|
||||||
if self.path == "/":
|
case "/endp":
|
||||||
self.header_setup()
|
ncnw = process_datetime_DICTS(fulltable(tabletbale))
|
||||||
with open("index.html", "rb") as file:
|
efg = json.dumps(
|
||||||
self.wfile.write(file.read())
|
[ # haha yeah right why cant you do it client side
|
||||||
return
|
## BIGGER QUESTION is that this is 2 of the same data
|
||||||
if self.path == "/style.css": # allowed files is funny
|
getnewdicttranslate(
|
||||||
self.header_setup(headers={"Content-Type": "text/css"})
|
i,
|
||||||
with open("style.css", "rb") as file:
|
scTrtb,
|
||||||
self.wfile.write(file.read())
|
)
|
||||||
return
|
for i in ncnw
|
||||||
if self.path == "/script.js": #
|
]
|
||||||
self.header_setup(
|
|
||||||
headers={"Content-Type": "text/javascript"}
|
|
||||||
) ## never knew!
|
|
||||||
with open("script.js", "rb") as file:
|
|
||||||
self.wfile.write(file.read())
|
|
||||||
return
|
|
||||||
|
|
||||||
(connectio, eror) = get_that_connection(connectionSettings)
|
|
||||||
if eror:
|
|
||||||
print("coneti eror: ", eror)
|
|
||||||
return
|
|
||||||
# HE. MUST. AVOID. THE. TRYCATCH
|
|
||||||
with connectio.cursor(buffered=True) as cur:
|
|
||||||
try:
|
|
||||||
res = cur.execute("select * from tbale")
|
|
||||||
w = cur.fetchall()
|
|
||||||
res = cur.execute(
|
|
||||||
"select column_name from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'tbale'"
|
|
||||||
)
|
)
|
||||||
anotherone2 = cur.fetchall()
|
self.header_setup(headers={"Content-type": "application/json"})
|
||||||
except Exception as e:
|
# self.wfile.write(str(c).encode())
|
||||||
print(e)
|
# self.wfile.write(str(anotherone2).encode())
|
||||||
return # return ealy no else
|
self.wfile.write(str(efg).encode())
|
||||||
c = process_datetime_tuples(w)
|
return
|
||||||
ncnw = funny_tuples_to_dicts_processor(anotherone2, c)
|
# wd = [(a["neme"], a["kewod"], a["cod"]) for a in ncnw]
|
||||||
|
# print(wd)
|
||||||
if self.path == "/endp":
|
# npnd = {i["neme"]: i for i in ncnw} # simple as
|
||||||
efg = json.dumps(
|
# # for p in npnd:
|
||||||
[ # haha yeah right why cant you do it client side
|
# a = npnd.get(self.path.lstrip("/"))
|
||||||
## BIGGER QUESTION is that this is 2 of the same data
|
with sqlcon.connect(**connectionSettings) as n:
|
||||||
getnewdicttranslate(
|
with n.cursor(prepared=True) as r:
|
||||||
i,
|
r.execute(
|
||||||
{"neme": "one", "kewod": "two", "cod": "three", "expi": "four"},
|
f"select neme, kewod, cod from {tabletbale} where neme = ?;",
|
||||||
)
|
(self.path.lstrip("/"),),
|
||||||
for i in ncnw
|
)
|
||||||
]
|
ee = r.fetchone()
|
||||||
)
|
if not ee:
|
||||||
self.header_setup(headers={"Content-type": "application/json"})
|
self.header_setup(rescode.NOT_FOUND)
|
||||||
# self.wfile.write(str(c).encode())
|
self.wfile.write(notfound404)
|
||||||
# self.wfile.write(str(anotherone2).encode())
|
|
||||||
self.wfile.write(str(efg).encode())
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
wd = [(a["neme"], a["kewod"], a["cod"]) for a in ncnw]
|
|
||||||
# print(wd)
|
|
||||||
for a, v, c in wd:
|
|
||||||
# print(a,v)
|
|
||||||
# print(self.path, a)
|
|
||||||
if self.path.lstrip("/") == a:
|
|
||||||
if c == 200:
|
|
||||||
self.header_setup(c, {"Content-type": "text/plain"})
|
|
||||||
self.wfile.write(v.encode()) if v else None ## i mean crashes are handled anyway things keep running as is
|
|
||||||
elif c in [301, 302]:
|
|
||||||
self.header_setup(c, {"Location": v})
|
|
||||||
return
|
|
||||||
self.header_setup(404)
|
|
||||||
self.wfile.write(
|
|
||||||
b"""
|
|
||||||
<h1>404</h1>
|
|
||||||
<p>where u at</p>
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
v, c = ee[1], ee[2] # value, code
|
||||||
|
# print(a,v)
|
||||||
|
# print(self.path, a)
|
||||||
|
# if self.path.lstrip("/") == p["neme"]:
|
||||||
|
# a, v, c
|
||||||
|
# print(v, c)
|
||||||
|
if v:
|
||||||
|
if c == rescode.OK:
|
||||||
|
self.header_setup(c, {"Content-type": "text/plain;charset=utf-8"})
|
||||||
|
self.wfile.write(v.encode())
|
||||||
|
## i mean crashes are handled anyway things keep running as is
|
||||||
|
# what bro sayin
|
||||||
|
return
|
||||||
|
elif c // 100 == 2:
|
||||||
|
pass
|
||||||
|
elif c // 100 == 3: # redirects
|
||||||
|
self.header_setup(c, {"Location": v})
|
||||||
|
return
|
||||||
|
# case what????
|
||||||
|
self.header_setup(rescode.OK)
|
||||||
|
self.wfile.write(
|
||||||
|
f'<p>u at <a href=".{pathObj.path}">{pathObj.path}</a>. probably content is None python said so idfk</p>'.encode()
|
||||||
|
)
|
||||||
|
if c == rescode.OK:
|
||||||
|
self.wfile.write(b"<p>this shouldve been a text file</p>")
|
||||||
|
elif c // 100 == 3:
|
||||||
|
self.wfile.write(b"<p>this shouldve been a redirect</p>")
|
||||||
|
return
|
||||||
|
|
||||||
def do_POST(self):
|
def do_POST(self):
|
||||||
self.youJustHaveToDoTheseStuff()
|
class lmao(Exception):
|
||||||
|
def __init__(
|
||||||
|
self, rc: int | rescode | None = None, case: int | None = None, *a, **kw
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
rc: rescode
|
||||||
|
case: special thingy. truly the hax
|
||||||
|
msg: msg!!!!
|
||||||
|
"""
|
||||||
|
super().__init__(rc, case, *a, **kw)
|
||||||
|
self.stupid = case
|
||||||
|
if type(rc) == int:
|
||||||
|
print("what")
|
||||||
|
self.ldarescode = rescode(rc) # why do i have to do this
|
||||||
|
print(self.ldarescode)
|
||||||
|
elif type(rc) == rescode:
|
||||||
|
print("good")
|
||||||
|
self.ldarescode = rc
|
||||||
|
print(self.ldarescode)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ldacause(self):
|
||||||
|
return self.__cause__
|
||||||
|
|
||||||
|
self.reallyEveryTime()
|
||||||
match self.path:
|
match self.path:
|
||||||
case "/close":
|
case "/close":
|
||||||
return self.close()
|
return self.close()
|
||||||
|
|
||||||
case "/endp":
|
case p if p != "/endp": # self.path
|
||||||
self.header_setup(headers={"Content-type": "text/plain"})
|
self.header_setup(rescode.FORBIDDEN)
|
||||||
content_type = self.headers.get("Content-Type")
|
self.wfile.write(notallowed403)
|
||||||
content_length = int(self.headers.get("Content-Length"))
|
return
|
||||||
with self.rfile as r:
|
try:
|
||||||
post_data_bytes = r.read(content_length)
|
content_type = self.headers.get("Content-Type", str())
|
||||||
## read how many bytes is the content length
|
content_length = int(self.headers.get("Content-Length"), int())
|
||||||
|
print("cccc", content_type, content_length)
|
||||||
|
with self.rfile as r:
|
||||||
|
post_data_bytes = r.read(content_length)
|
||||||
|
## read how many bytes is the content length
|
||||||
|
|
||||||
self.wfile.write(
|
if content_type != "application/json":
|
||||||
b"Ive got a POST at "
|
raise lmao(rescode.OK, 1)
|
||||||
+ self.headers.get("Origin", "nowhere lmao").encode()
|
# self.wfile.write(b"its of the type: ")
|
||||||
+ b" from "
|
# self.wfile.write(content_type.encode())
|
||||||
+ self.headers.get("Referer", "who?").encode()
|
|
||||||
+ b" with the following data:\n"
|
try:
|
||||||
+ post_data_bytes
|
data_dict: dict = json.loads(post_data_bytes)
|
||||||
|
##
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
raise lmao(rescode.BAD_REQUEST, 2) from e
|
||||||
|
# print(e)
|
||||||
|
# self.header_setup(
|
||||||
|
# code=rescode.BAD_REQUEST,
|
||||||
|
# headers={"Content-type": "text/plain"},
|
||||||
|
# )
|
||||||
|
# self.wfile.write(
|
||||||
|
# b"haha your data sucks (json.loads is not necessarily strict/bad, its just u sent bad): "
|
||||||
|
# + str(e).encode()
|
||||||
|
# )
|
||||||
|
|
||||||
|
##
|
||||||
|
# print((*data_dict.keys(), *data_dict.values()))
|
||||||
|
##
|
||||||
|
if data_dict.get("from") == "ldlda":
|
||||||
|
# ogdata_dict = data_dict.copy() ## as this isnt deep copy also because the thing is short lived i guess i dont ever need this for anything
|
||||||
|
# print("b4: ", data_dict, ogdata_dict) ## initial state for comp
|
||||||
|
data_dict = getnewdicttranslate(
|
||||||
|
# ogdata_dict[
|
||||||
|
data_dict[
|
||||||
|
"data"
|
||||||
|
], ## this would actually change ogdatadict.data ## OR NOT
|
||||||
|
csTrtb,
|
||||||
)
|
)
|
||||||
|
# print(
|
||||||
|
# "aftr: ", data_dict, ogdata_dict
|
||||||
|
# ) ## notice that the thing changed.
|
||||||
|
##
|
||||||
|
|
||||||
if content_type == "application/json":
|
wwwww = tuple(key for key in data_dict if key in colnmaes)
|
||||||
|
# hmmm
|
||||||
|
# repated cod? huh?
|
||||||
|
|
||||||
|
updated_Verybreakablequery_insert_into = (
|
||||||
|
f"insert into {tabletbale} "
|
||||||
|
+ "({0}) values ({0})".format( ## LEARN PYTHON SQL this is nasty
|
||||||
|
",".join(("{}",) * len(wwwww)) # incredibly real update
|
||||||
|
).format(*wwwww, *("?",) * len(wwwww))
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
wwwww,
|
||||||
|
tuple(data_dict[w] for w in wwwww),
|
||||||
|
updated_Verybreakablequery_insert_into,
|
||||||
|
sep="\n",
|
||||||
|
)
|
||||||
|
##
|
||||||
|
try:
|
||||||
|
with sqlcon.connect(**connectionSettings) as conn:
|
||||||
|
# a = connectio.autocommit # archiver
|
||||||
|
conn.autocommit = (
|
||||||
|
True # where is my ASDFCKjugsadkfjywgefdklajegdlagf
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
data_dict: dict = json.loads(post_data_bytes)
|
with conn.cursor(prepared=True) as cur:
|
||||||
##
|
conn.autocommit = True # WHERE!!!! IS COMMIT!!!!!!!
|
||||||
except Exception as e:
|
cur.execute(
|
||||||
print(e)
|
|
||||||
self.wfile.write(
|
|
||||||
b"\nhaha your data sucks (json.load is strict/bad): "
|
|
||||||
+ str(e).encode()
|
|
||||||
)
|
|
||||||
return
|
|
||||||
##
|
|
||||||
(connectio, eror) = get_that_connection(connectionSettings)
|
|
||||||
##
|
|
||||||
if eror:
|
|
||||||
print("coneti eror: ", eror)
|
|
||||||
self.wfile.write(
|
|
||||||
b"the thing cant even start like what f: "
|
|
||||||
+ str(eror).encode()
|
|
||||||
)
|
|
||||||
return
|
|
||||||
##
|
|
||||||
# print((*data_dict.keys(), *data_dict.values()))
|
|
||||||
|
|
||||||
with connectio.cursor(buffered=True) as cur:
|
|
||||||
try:
|
|
||||||
anotherone = cur.execute(
|
|
||||||
"select column_name from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'tbale'"
|
|
||||||
)
|
|
||||||
this_list_of_colnaes = cur.fetchall()
|
|
||||||
except Exception as e:
|
|
||||||
print("to day i cant get the damn colums: ", e)
|
|
||||||
this_list_of_colnaes = [u[0] for u in this_list_of_colnaes] # weird
|
|
||||||
##
|
|
||||||
if data_dict.get("from") == "ldlda":
|
|
||||||
ogdata_dict = data_dict.copy() ## as this isnt deep copy also because the thing is short lived i guess i dont ever need this for anything
|
|
||||||
print("b4: ",data_dict, ogdata_dict) ## initial state for comp
|
|
||||||
data_dict = getnewdicttranslate(
|
|
||||||
ogdata_dict["data"], ## this would actually change ogdatadict.data
|
|
||||||
{
|
|
||||||
"one": "neme",
|
|
||||||
"two": "kewod",
|
|
||||||
"three": "cod",
|
|
||||||
"four": "expi",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
print("aftr: ",data_dict, ogdata_dict) ## notice that the thing changed.
|
|
||||||
##
|
|
||||||
|
|
||||||
wwwww = tuple(
|
|
||||||
key for key in data_dict if key in this_list_of_colnaes
|
|
||||||
)
|
|
||||||
# hmmm
|
|
||||||
# repated cod? huh?
|
|
||||||
|
|
||||||
updated_Verybreakablequery_insert_into = ( ## LEARN PYTHON SQL this is nasty
|
|
||||||
"insert into tbale ({0}) values ({0})".format(
|
|
||||||
",".join(["{}"] * len(wwwww))
|
|
||||||
).format(*wwwww, *("?",) * len(wwwww))
|
|
||||||
)
|
|
||||||
print(
|
|
||||||
wwwww,
|
|
||||||
tuple(data_dict[w] for w in wwwww),
|
|
||||||
updated_Verybreakablequery_insert_into,
|
|
||||||
sep="\n",
|
|
||||||
)
|
|
||||||
|
|
||||||
with connectio.cursor(prepared=True) as cur:
|
|
||||||
connectio.autocommit = True
|
|
||||||
try:
|
|
||||||
res = cur.execute(
|
|
||||||
updated_Verybreakablequery_insert_into,
|
updated_Verybreakablequery_insert_into,
|
||||||
tuple(data_dict[w] for w in wwwww),
|
tuple(data_dict[w] for w in wwwww),
|
||||||
# multi=True,
|
# multi=True,
|
||||||
)
|
)
|
||||||
print("insert into qure: ", cur.fetchall())
|
conn.commit() # WHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWHYWH
|
||||||
another = cur.execute("select * from tbale")
|
cur.execute(
|
||||||
w2f = cur.fetchall()
|
f"select * from tbale where neme = ?",
|
||||||
##
|
(data_dict["neme"],),
|
||||||
except Exception as e:
|
|
||||||
print("execute err: ", e)
|
|
||||||
self.wfile.write(
|
|
||||||
b"\n is it very much Invalid: " + str(e).encode()
|
|
||||||
)
|
)
|
||||||
##
|
print("res of:", cur.fetchone())
|
||||||
else:
|
# e = cur.fetchall()
|
||||||
# print(cur)
|
# print("insert into qure: ")
|
||||||
# cur.execute("select * from tbale")
|
# e = str(e)
|
||||||
# aq142 = cur.fetchall()
|
# map(lambda a, b: e.replace(a, b), severColum, clietColum)
|
||||||
# self.do_GET()
|
# with self.wfile as wf:
|
||||||
pass
|
# wf.write(b"uh what you mightve submitted SuperSsdajfhgaswjkdfaw "+e.encode())
|
||||||
##
|
# another = cur.execute("select * from tbale")
|
||||||
# self.wfile.write(b"\n We have this in the this: ")
|
# w2f = cur.fetchall()
|
||||||
# self.wfile.write(str(process_datetime_tuples(w2f)).encode())
|
##
|
||||||
|
except sqlcon.Error as er:
|
||||||
|
raise lmao(rescode.BAD_REQUEST, 3) from er
|
||||||
|
# print("execute err: ", er)
|
||||||
|
# q = str(er)
|
||||||
|
# map(
|
||||||
|
# lambda a, b: q.replace(a, b),
|
||||||
|
# severColum,
|
||||||
|
# clietColum,
|
||||||
|
# )
|
||||||
|
|
||||||
## what is a get to endp
|
# self.header_setup(
|
||||||
else: # elif content-type != json
|
# code=rescode.BAD_REQUEST,
|
||||||
self.wfile.write(b"\nits of the type: ")
|
# headers={"Content-type": "text/plain"},
|
||||||
self.wfile.write(content_type.encode())
|
# )
|
||||||
|
# self.wfile.write(
|
||||||
|
# b"is it very much Invalid: "
|
||||||
|
# + q.encode()
|
||||||
|
# + b"\n funny Stuff: q=str(error);map(lambda a, b: q.replace(a, b), severColum, clietColum)"
|
||||||
|
# )
|
||||||
|
|
||||||
case _: # self.path
|
##
|
||||||
self.header_setup(403)
|
else:
|
||||||
self.wfile.write(
|
raise lmao(rescode.CREATED, 4)
|
||||||
b"""
|
# self.header_setup(
|
||||||
<h1>403</h1>
|
# code=rescode.CREATED,
|
||||||
<p>tf u doin</p>
|
# headers={"Content-type": "text/plain"},
|
||||||
"""
|
# )
|
||||||
)
|
|
||||||
|
|
||||||
return
|
# print(cur)
|
||||||
|
# cur.execute("select * from tbale")
|
||||||
|
# aq142 = cur.fetchall()
|
||||||
|
# self.do_GET()
|
||||||
|
# pass
|
||||||
|
##
|
||||||
|
# finally:
|
||||||
|
# connectio.autocommit = a
|
||||||
|
except sqlcon.Error as eror:
|
||||||
|
raise lmao(rescode.INTERNAL_SERVER_ERROR, 5) from eror
|
||||||
|
# print("coneti eror: ", eror)
|
||||||
|
# self.header_setup(
|
||||||
|
# code=rescode.INTERNAL_SERVER_ERROR,
|
||||||
|
# headers={"Content-type": "text/plain"},
|
||||||
|
# )
|
||||||
|
# self.wfile.write(
|
||||||
|
# b"the thing cant even start like what f: " + str(eror).encode()
|
||||||
|
# )
|
||||||
|
except lmao as e:
|
||||||
|
print(e.args)
|
||||||
|
efg = (
|
||||||
|
f'Ive got a POST at {self.headers.get("Origin", "_nowhere lmao_")} from {self.headers.get("Referer", "_who?_")} with the following data:\n'.encode()
|
||||||
|
+ (
|
||||||
|
post_data_bytes
|
||||||
|
or b"nothing??? what? (no fr nothing fr ALSO YOU KNOW YOUR OWN POST????????????)"
|
||||||
|
) # why so hectic
|
||||||
|
+ b"\n"
|
||||||
|
)
|
||||||
|
headerWhat = {"Content-type": "text/plain;charset=utf-8"} # tf
|
||||||
|
match e.stupid:
|
||||||
|
case 1:
|
||||||
|
print("cccc", content_type, content_length)
|
||||||
|
|
||||||
|
self.header_setup(
|
||||||
|
code=e.ldarescode,
|
||||||
|
headers=headerWhat,
|
||||||
|
)
|
||||||
|
self.wfile.write(efg)
|
||||||
|
self.wfile.write(b"its of the type: ")
|
||||||
|
self.wfile.write(content_type.encode() or b"fdahjklfdashkjlasdf")
|
||||||
|
case 2:
|
||||||
|
cc = e.ldacause
|
||||||
|
print(cc)
|
||||||
|
self.header_setup(
|
||||||
|
code=rescode.BAD_REQUEST,
|
||||||
|
headers=headerWhat,
|
||||||
|
)
|
||||||
|
self.wfile.write(efg)
|
||||||
|
self.wfile.write(
|
||||||
|
b"haha your data sucks (json.loads is not necessarily strict/bad, its just u sent bad): "
|
||||||
|
+ str(cc).encode()
|
||||||
|
)
|
||||||
|
case 3:
|
||||||
|
cc = e.ldacause
|
||||||
|
# print("execute err: ", cc)
|
||||||
|
q = str(cc)
|
||||||
|
for a, b in zip(severColum, clietColum):
|
||||||
|
q = q.replace(a, b)
|
||||||
|
# print("execute errd: ", q)
|
||||||
|
self.header_setup(
|
||||||
|
code=rescode.BAD_REQUEST,
|
||||||
|
headers=headerWhat,
|
||||||
|
)
|
||||||
|
self.wfile.write(efg)
|
||||||
|
self.wfile.write(
|
||||||
|
b"is it very much Invalid: "
|
||||||
|
+ q.encode()
|
||||||
|
+ b"\n funny Stuff: # replace strings found in list old to same index in list new. used for, zip, string.replace"
|
||||||
|
)
|
||||||
|
case 4:
|
||||||
|
self.header_setup(
|
||||||
|
code=rescode.CREATED,
|
||||||
|
headers=headerWhat,
|
||||||
|
)
|
||||||
|
self.wfile.write(efg)
|
||||||
|
case 5:
|
||||||
|
cc = e.ldacause
|
||||||
|
print("coneti eror: ", cc)
|
||||||
|
self.header_setup(
|
||||||
|
code=rescode.INTERNAL_SERVER_ERROR,
|
||||||
|
headers=headerWhat,
|
||||||
|
)
|
||||||
|
self.wfile.write(efg)
|
||||||
|
self.wfile.write(
|
||||||
|
b"the thing cant even start like what f: " + str(cc).encode()
|
||||||
|
)
|
||||||
|
# self.wfile.write(b"\n We have this in the this: ")
|
||||||
|
# self.wfile.write(str(process_datetime_tuples(w2f)).encode())
|
||||||
|
|
||||||
|
## what is a get to endp
|
||||||
|
# elif content-type != json
|
||||||
|
|
||||||
|
|
||||||
# out
|
if __name__ == "__main__":
|
||||||
|
pass
|
||||||
|
|
||||||
# def __do_POST2(self):
|
# rememver
|
||||||
# if self.path == "/close":
|
# with
|
||||||
# return self.close()
|
# def a(f)
|
||||||
# self.header_setup()
|
# def m(c)
|
||||||
# content_length = int(self.headers["Content-Length"])
|
# return f(c)
|
||||||
# with self.rfile as r:
|
# return m
|
||||||
# post_data_bytes = self.rfile.read(content_length)
|
#
|
||||||
# self.wfile.write(
|
# @a
|
||||||
# b"MY SERVER: The post data I received from the request has following data:\n"
|
# def b(c)
|
||||||
# + post_data_bytes
|
# equals
|
||||||
# )
|
# def b(c)
|
||||||
# try:
|
# b = a(b)
|
||||||
# data_dict = json.loads(post_data_bytes.decode("utf-8"))
|
|
||||||
# except Exception as e:
|
|
||||||
# print(e)
|
|
||||||
# try:
|
|
||||||
# connectio = sqlcon.connect(**connectionSettings)
|
|
||||||
# connectio.autocommit = True # EUYOEYOEYOEYOEYO
|
|
||||||
# except sqlcon.Error as e:
|
|
||||||
# print(e.errno, e.msg)
|
|
||||||
# else:
|
|
||||||
# with connectio.cursor(buffered=True) as cur:
|
|
||||||
# try:
|
|
||||||
# res = cur.execute(
|
|
||||||
# "insert into tbale (kewod, id) values (%s, %s)",
|
|
||||||
# (
|
|
||||||
# data_dict["kewod"],
|
|
||||||
# data_dict["id"],
|
|
||||||
# ),
|
|
||||||
# multi=True,
|
|
||||||
# )
|
|
||||||
|
|
||||||
# print(res)
|
# so if
|
||||||
# except Exception as e:
|
# @a(x)
|
||||||
# print("execute err: ", e)
|
# def b(c)
|
||||||
# self.wfile.write(b"\n is it very much Invalid." + str(e).encode())
|
# a should be
|
||||||
# else:
|
# def a(x)
|
||||||
# print(cur)
|
# def w(b)
|
||||||
# cur.execute("select * from tbale")
|
# def m(c)
|
||||||
# self.wfile.write(
|
# return b(c)
|
||||||
# b"\n We have this in the this: "
|
# return m
|
||||||
# + str.encode(str(cur.fetchall()))
|
# return w
|
||||||
# )
|
|
||||||
# return
|
|
||||||
|
|
||||||
# def __do_GET2(self):
|
# you_thought_you_are_funny_helper = {"GET":{}, "POST":{}}
|
||||||
# if self.path == "/close":
|
# def you_thought_you_are_funny(
|
||||||
# return self.close()
|
# serverHandler, # classHUH how Would i get the class instance tho huh
|
||||||
|
# method: Literal["GET", "POST"],
|
||||||
|
# webpath: str,
|
||||||
|
# resCode: int,
|
||||||
|
# headers: dict,
|
||||||
|
# ):
|
||||||
|
# # no yo not
|
||||||
|
# """
|
||||||
|
# @gay("GET", '/', 200, {"Content-type":"text/html"})
|
||||||
|
# def handlerMethod(self, why, do, i, do, this):
|
||||||
|
# return "gay"
|
||||||
|
# """
|
||||||
|
# def g(ggg):
|
||||||
|
# you_thought_you_are_funny_helper[method] = ggg #no more understand
|
||||||
|
# def gg(serverHandler, *gggg, **ggggg):
|
||||||
|
# serverHandler.header_setup(resCode, headers)
|
||||||
|
# return ggg(serverHandler, *gggg, **ggggg)
|
||||||
|
|
||||||
# self.header_setup()
|
# return gg
|
||||||
# try:
|
|
||||||
# connectio = sqlcon.connect(**connectionSettings)
|
|
||||||
# except sqlcon.Error as e:
|
|
||||||
# print(e)
|
|
||||||
# else:
|
|
||||||
# with connectio.cursor(buffered=True, raw=True) as cur:
|
|
||||||
# try:
|
|
||||||
# res = cur.execute("select * from tbale")
|
|
||||||
# w = cur.fetchall()
|
|
||||||
# except Exception as e:
|
|
||||||
# print(e)
|
|
||||||
# else:
|
|
||||||
# print(w)
|
|
||||||
# self.wfile.write(bytes(w).decode())
|
|
||||||
# return
|
|
||||||
|
|
||||||
# def __close2(self):
|
# # this is So not ok SCRAP
|
||||||
# try:
|
# return g
|
||||||
# self.server.server_close()
|
|
||||||
# except BaseException as e:
|
|
||||||
# print(e)
|
|
||||||
# finally:
|
|
||||||
# print("gato")
|
|
||||||
# raise SystemExit("truly the /close")
|
|
||||||
# do i need the funny trycatch ONCE
|
|
||||||
# def close(self):
|
|
||||||
# funny_trycatch_wrapper(
|
|
||||||
# tries=[(self.server.server_close)],
|
|
||||||
# finallies=[(print, ("gato")), ('raise SystemExit("truly the /close")')],
|
|
||||||
# )
|
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
from typing import Callable, Dict, Any, List, Tuple, Union
|
from collections import defaultdict
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
from typing import Callable, Dict, Any, List, Literal, Tuple, Union
|
||||||
from itertools import zip_longest
|
from itertools import zip_longest
|
||||||
import datetime
|
import datetime
|
||||||
import copy
|
import copy
|
||||||
@@ -116,7 +119,7 @@ def function_splitter(
|
|||||||
works like your function caller, (function, (args), {kwargs})
|
works like your function caller, (function, (args), {kwargs})
|
||||||
function(*oa, **args, **okwa, **kwargs) # funny order huhg
|
function(*oa, **args, **okwa, **kwargs) # funny order huhg
|
||||||
|
|
||||||
Execute a function or a string using eval if it's the only argument.
|
Execute a function or a string using exec????? if it's the only argument.
|
||||||
|
|
||||||
:param t: Tuple containing a function or string, args, and kwargs.
|
:param t: Tuple containing a function or string, args, and kwargs.
|
||||||
:param e: Additional positional arguments.
|
:param e: Additional positional arguments.
|
||||||
@@ -259,9 +262,32 @@ def process_datetime_tuples(
|
|||||||
return processed_tuples
|
return processed_tuples
|
||||||
|
|
||||||
|
|
||||||
|
def process_datetime_DICTS(
|
||||||
|
dicts: List[Dict[str, Any]], action: Literal["timestamp", "string"] = "timestamp"
|
||||||
|
) -> List[Dict[str, Any]]:
|
||||||
|
"""check process datetime tuples"""
|
||||||
|
for dict in dicts:
|
||||||
|
for k, v in dict.items():
|
||||||
|
if isinstance(v, datetime.datetime):
|
||||||
|
if action == "string":
|
||||||
|
dict[k] = v.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
elif action == "timestamp":
|
||||||
|
dict[k] = v.timestamp()
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported action {action}. Use 'string' or 'timestamp'.") # bet this will run
|
||||||
|
return dicts # in place processing
|
||||||
|
|
||||||
|
|
||||||
def funny_tuples_to_dicts_processor(colname: list[tuple], coldata: list[tuple]):
|
def funny_tuples_to_dicts_processor(colname: list[tuple], coldata: list[tuple]):
|
||||||
|
"""
|
||||||
|
sql return such shit
|
||||||
|
"""
|
||||||
if len(colname) != len(coldata[0]):
|
if len(colname) != len(coldata[0]):
|
||||||
raise ValueError("unless im stupid, even then curate ur list first")
|
raise IndexError(
|
||||||
|
"unless im stupid, even then curate ur list first.",
|
||||||
|
f"size of first arg {len(colname)} != second arg {len(coldata[0])}",
|
||||||
|
)
|
||||||
new_dicts: list[dict] = []
|
new_dicts: list[dict] = []
|
||||||
for ee in coldata:
|
for ee in coldata:
|
||||||
new_dict = {}
|
new_dict = {}
|
||||||
@@ -271,5 +297,110 @@ def funny_tuples_to_dicts_processor(colname: list[tuple], coldata: list[tuple]):
|
|||||||
return new_dicts
|
return new_dicts
|
||||||
|
|
||||||
|
|
||||||
getnewdict = lambda d, l: {k: d[k] for k in d if k in l}
|
getnewdictl = lambda d, l: {k: d[k] for k in d if k in l}
|
||||||
getnewdicttranslate = lambda d, tltb: {tltb[k]: d[k] for k in d if k in tltb}
|
|
||||||
|
|
||||||
|
def getnewdict(d: dict, l: list) -> dict:
|
||||||
|
"""
|
||||||
|
from a list of keys filter that dict (filter)
|
||||||
|
"""
|
||||||
|
return {k: d[k] for k in d if k in l}
|
||||||
|
|
||||||
|
|
||||||
|
getnewdicttranslatel = lambda d, tltb: {tltb[k]: d[k] for k in d if k in tltb}
|
||||||
|
|
||||||
|
|
||||||
|
def getnewdicttranslate(d: dict, tltb: dict) -> dict:
|
||||||
|
"""
|
||||||
|
from (key: value) of dict to (value of translate table: value of dict)
|
||||||
|
"""
|
||||||
|
return {tltb[k]: d[k] for k in d if k in tltb}
|
||||||
|
|
||||||
|
|
||||||
|
def lists_toDict_funnyaf(k: list, v: list):
|
||||||
|
"""thank you chat"""
|
||||||
|
d = {}
|
||||||
|
dup = defaultdict(list)
|
||||||
|
# if len(l1) != len(l2):
|
||||||
|
# raise ValueError("not equal lsit")
|
||||||
|
for key, val in zip_longest(k, v):
|
||||||
|
if key in d and d[key] != val:
|
||||||
|
dup[key].append(val)
|
||||||
|
d[key] = val
|
||||||
|
return d, dict(dup)
|
||||||
|
|
||||||
|
|
||||||
|
def simpler_ltd(k, v):
|
||||||
|
if len(k) != len(v):
|
||||||
|
raise ValueError("wrong size")
|
||||||
|
return dict(zip(k, v))
|
||||||
|
|
||||||
|
|
||||||
|
def zipSkipNone(*its, noneValue=None):
|
||||||
|
if len(its) == 0:
|
||||||
|
raise TypeError("wfehiufwehiu", noneValue + " where")
|
||||||
|
for i in zip(*its):
|
||||||
|
if any(a == noneValue for a in i):
|
||||||
|
# print(f"none: {i}")
|
||||||
|
continue
|
||||||
|
yield i
|
||||||
|
|
||||||
|
|
||||||
|
def rN(a=6, b=24):
|
||||||
|
return random.randint(a, b)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
l = [*string.digits, None]
|
||||||
|
a = random.choices(l, k=rN())
|
||||||
|
b = random.choices(l, k=rN())
|
||||||
|
c = random.choices(l, k=rN())
|
||||||
|
print(a, b, c, list(zipSkipNone(a, b, c)), sep="\n")
|
||||||
|
|
||||||
|
|
||||||
|
def HowToDecorator(*a1, **k1):
|
||||||
|
print("your decorator looks like this:")
|
||||||
|
print("@HowToDecorator(something)")
|
||||||
|
print(
|
||||||
|
"this is a decorator maker. right. as if you put something different the returned function from this HowToDecorator will have the different something"
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
"as where this is ran, its when you are trying to make a decorator from the decorator maker. \nIf i do this: deco = decomaker(**arguments) then use the @deco as normal, i will be running this print call once, and not again."
|
||||||
|
)
|
||||||
|
print(f"just so you know u put {a1} as pos args and {k1} as kwargs")
|
||||||
|
|
||||||
|
# the decorator will decorate the function like this:
|
||||||
|
# if i write
|
||||||
|
# @d
|
||||||
|
# def b()
|
||||||
|
# its the same as saying b = d(b)
|
||||||
|
def TheDecorator(function):
|
||||||
|
print("if you dont have parenthesis")
|
||||||
|
print(
|
||||||
|
"@TheDecorator \\n def fn() for example, then its like calling this TheDecorator func with (fn) as the arg"
|
||||||
|
)
|
||||||
|
print(f"u can access {a1} and {k1} here as well")
|
||||||
|
print(
|
||||||
|
"any time you are using the deco (which is decomaker(**arguments)) then you are calling this print"
|
||||||
|
)
|
||||||
|
|
||||||
|
def SupportForArgs(*a2, **k2):
|
||||||
|
print("if you are running function early, then this is great.")
|
||||||
|
print("you can modify the args here, add some, take some idk")
|
||||||
|
print(
|
||||||
|
"imagine instead of function(arg) ur running SupportForArgs(arg) instead"
|
||||||
|
)
|
||||||
|
returnValue = function(*a1, *a2, **k1, **k2)
|
||||||
|
print("this line of text appears anytime a function decorated gets called")
|
||||||
|
print("you can append do stuff with the decorated function and its result")
|
||||||
|
return "something else?", returnValue
|
||||||
|
|
||||||
|
print(
|
||||||
|
"the decorator could just return function as normal, running things. but with the inner function it can also change stuff with the calling of the function itself."
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
"i believe in having an inner function (support for args) here even if you dont do anything (rare af)"
|
||||||
|
)
|
||||||
|
return SupportForArgs
|
||||||
|
|
||||||
|
return TheDecorator
|
||||||
@@ -5,10 +5,10 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>lđa testing</title>
|
<title>lđa testing</title>
|
||||||
<link type="text/css" rel="stylesheet" href="./style.css" />
|
<link type="text/css" rel="stylesheet" href="./index/style.css" />
|
||||||
<!-- huh? what? -->
|
<!-- huh? what? -->
|
||||||
<script type="module" src="./script.js" defer></script>
|
<script type="module" src="./index/script.js" defer></script>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css" />
|
||||||
<!-- real -->
|
<!-- real -->
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -36,29 +36,45 @@
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<form action="./endp" method="post" id="only_form" enctype="text/plain">
|
<form action="./endp" method="post" id="only_form" enctype="text/plain">
|
||||||
<label for="oneid">url (no space please thanks)
|
<label for="oneid">url (no space please thanks)
|
||||||
<div style=>
|
<div style>
|
||||||
<a id="woah" style="text-align: right; min-width: 240px;
|
<a id="woah" style="text-align: right; min-width: 240px"></a>
|
||||||
"></a>
|
<input style="display: inline" required type="text" name="one" id="oneid" placeholder="url"
|
||||||
<input style="display: inline;" required type="text" name="one" id="oneid" placeholder="url"
|
|
||||||
maxlength="15" pattern="\S+" />
|
maxlength="15" pattern="\S+" />
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<label for="the_Textarea">content (idk how it works anymore):
|
<label for="the_Textarea">content (idk how it works anymore):
|
||||||
|
</label>
|
||||||
|
<span id="i_appear" hidden>so uh if you choose redirect then this should be a complete link and nothing
|
||||||
|
else uh example <a target="_blank" href="https://ldlda.com">https://ldlda.com</a> uh</span>
|
||||||
|
<div>
|
||||||
<div class="setting-buttons">
|
<div class="setting-buttons">
|
||||||
<!-- <input type="button" id="viewTextarea" value="show textarea" /> -->
|
<!-- <input type="button" id="viewTextarea" value="show textarea" /> -->
|
||||||
<input type="button" id="viewDiv" value="show rendered" />
|
<input type="button" id="viewDiv" value="show rendered" />
|
||||||
<input type="button" value="markdown to html" id="translateMD">
|
<input type="button" value="markdown to html" id="translateMD" />
|
||||||
<input type="checkbox" id="auto_translate">
|
<label for="auto_translate"><input type="checkbox" id="auto_translate" /> auto (lag)</label>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
<textarea required class="why" name="two" id="the_Textarea" placeholder="what"></textarea>
|
||||||
<div>
|
|
||||||
<textarea class="why" name="two" id="the_Textarea" placeholder="what"></textarea>
|
|
||||||
<!-- <div class="why" name="two" id="the_div" placeholder="type in here"></div> -->
|
<!-- <div class="why" name="two" id="the_div" placeholder="type in here"></div> -->
|
||||||
</div>
|
</div>
|
||||||
<label for="threeid">response code if path visited. Default 200<input type="number" name="three"
|
<label for="threeid"><span style="display: block;">response code if path visited. Default 200</span>
|
||||||
id="threeid" placeholder="http res code" min="0" pattern="\d*" /></label>
|
<select required name="three" id="threeid">
|
||||||
|
<option value="" disabled>-- CHOOSE --</option>
|
||||||
|
<optgroup label="content">
|
||||||
|
<option selected value="200">text file</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="redirect">
|
||||||
|
<option value="302">shortlinks</option>
|
||||||
|
<option value="301">shortlinks permanent</option>
|
||||||
|
</optgroup>
|
||||||
|
<option id="uniqueID">do NOT:</option>
|
||||||
|
</select>
|
||||||
|
<input type="number" id="rescode" placeholder="advanced type shi" style="width: 5em; display: none;"
|
||||||
|
min="100" max="599" step="1">
|
||||||
|
</label>
|
||||||
<label for="fourid">expiration time for anything (todo idk how to do )<input type="number" name="four"
|
<label for="fourid">expiration time for anything (todo idk how to do )<input type="number" name="four"
|
||||||
id="fourid" placeholder="expiration in days" min="0" pattern="\d*" /></label>
|
id="fourid" placeholder="expiration in days" pattern="\d{1,3}" min="0" max="255"
|
||||||
|
step="1" /></label>
|
||||||
|
<!-- bulletproof -->
|
||||||
<p>leave empty for none / default</p>
|
<p>leave empty for none / default</p>
|
||||||
<input type="submit" value="Sumit rn" />
|
<input type="submit" value="Sumit rn" />
|
||||||
</form>
|
</form>
|
||||||
@@ -59,7 +59,7 @@ const translateMDButton = document.getElementById("translateMD");
|
|||||||
const MDtoHTMLEngine = (v) =>
|
const MDtoHTMLEngine = (v) =>
|
||||||
micromark(v, {
|
micromark(v, {
|
||||||
extensions: [frontmatter(), gfm(), math()],
|
extensions: [frontmatter(), gfm(), math()],
|
||||||
htmlExtensions: [frontmatterHtml(), gfmHtml(), mathHtml()],
|
htmlExtensions: [frontmatterHtml(), gfmHtml(), mathHtml()], // please if i can CodeHighlight maybe PLEAS
|
||||||
});
|
});
|
||||||
const updateMD = (e) => {
|
const updateMD = (e) => {
|
||||||
divTextarea.innerHTML = MDtoHTMLEngine(realTextarea.value);
|
divTextarea.innerHTML = MDtoHTMLEngine(realTextarea.value);
|
||||||
@@ -68,12 +68,23 @@ const updateMD = (e) => {
|
|||||||
translateMDButton.addEventListener("click", updateMD);
|
translateMDButton.addEventListener("click", updateMD);
|
||||||
//
|
//
|
||||||
let updatingInterval = 240;
|
let updatingInterval = 240;
|
||||||
let justUpdated = false;
|
// let justUpdated = false;
|
||||||
let updateTimeout;
|
let updateTimeout;
|
||||||
|
// let a = 0 // was trying to make a hey why do i have to translate your every keystroke??????? thingamajig
|
||||||
const typingHandler = (f) => (e) => {
|
const typingHandler = (f) => (e) => {
|
||||||
if (!justUpdated && !updateTimeout) {
|
// a++
|
||||||
justUpdated = true;
|
// if (a > 4) { // thats 12wpm
|
||||||
|
// a = 0
|
||||||
|
// if (updateTimeout)
|
||||||
|
// clearTimeout(updateTimeout);
|
||||||
|
// updateTimeout = undefined;
|
||||||
|
// }
|
||||||
|
if (
|
||||||
|
// !justUpdated &&
|
||||||
|
!updateTimeout) {
|
||||||
|
// justUpdated = true;
|
||||||
updateTimeout = setTimeout(() => {
|
updateTimeout = setTimeout(() => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
f();
|
f();
|
||||||
document.getElementById("errorfrommd").textContent = null;
|
document.getElementById("errorfrommd").textContent = null;
|
||||||
@@ -81,10 +92,12 @@ const typingHandler = (f) => (e) => {
|
|||||||
document.getElementById("errorfrommd").textContent = e.message;
|
document.getElementById("errorfrommd").textContent = e.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
justUpdated = false;
|
// justUpdated = false;
|
||||||
updateTimeout = null;
|
clearTimeout(updateTimeout)
|
||||||
|
updateTimeout = undefined;
|
||||||
}, updatingInterval);
|
}, updatingInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
const mdUpdatingHandler = typingHandler(updateMD); //why
|
const mdUpdatingHandler = typingHandler(updateMD); //why
|
||||||
document.getElementById("auto_translate").addEventListener("change", (e) => {
|
document.getElementById("auto_translate").addEventListener("change", (e) => {
|
||||||
@@ -109,10 +122,10 @@ const click_out_the_div = (e) => {
|
|||||||
divTextarea.addEventListener("focus", click_in_the_div); // if function () {}
|
divTextarea.addEventListener("focus", click_in_the_div); // if function () {}
|
||||||
divTextarea.addEventListener("blur", click_out_the_div); // i can use this
|
divTextarea.addEventListener("blur", click_out_the_div); // i can use this
|
||||||
|
|
||||||
const resizeObserver = new ResizeObserver((mutation) => [
|
// const resizeObserver = new ResizeObserver((mutation) => [
|
||||||
mutation[0].contentRect.width,
|
// mutation[0].contentRect.width,
|
||||||
mutation[0].contentRect.height,
|
// mutation[0].contentRect.height,
|
||||||
]);
|
// ]);
|
||||||
|
|
||||||
divTextarea.style.setProperty;
|
divTextarea.style.setProperty;
|
||||||
const toggleDivTextarea = document.getElementById("viewDiv");
|
const toggleDivTextarea = document.getElementById("viewDiv");
|
||||||
@@ -130,6 +143,44 @@ document.querySelectorAll('input[type="number"]').forEach((e) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const selectorAll = document.getElementById("threeid");
|
||||||
|
const AlertOfAllTime = document.getElementById("i_appear");
|
||||||
|
const optionOfTheYear = document.getElementById("uniqueID");
|
||||||
|
const advancedTypeShit = document.getElementById("rescode");
|
||||||
|
const haxxor = (e) => {
|
||||||
|
if (/^[1-5][0-9][0-9]$/.test(advancedTypeShit.value)) {
|
||||||
|
advancedTypeShit.setCustomValidity("");
|
||||||
|
optionOfTheYear.value = advancedTypeShit.value;
|
||||||
|
} else {
|
||||||
|
advancedTypeShit.setCustomValidity(
|
||||||
|
"seems like its not a valid status code. i think its numbers from 100 to 599"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
selectorAll.addEventListener("change", function (e) {
|
||||||
|
if (this.value == "301" || this.value == "302") {
|
||||||
|
AlertOfAllTime.hidden = false;
|
||||||
|
} else {
|
||||||
|
AlertOfAllTime.hidden = true;
|
||||||
|
}
|
||||||
|
console.log(
|
||||||
|
selectorAll.selectedOptions[0],
|
||||||
|
optionOfTheYear,
|
||||||
|
selectorAll.selectedOptions[0] == optionOfTheYear
|
||||||
|
);
|
||||||
|
});
|
||||||
|
selectorAll.addEventListener("change", (e) => {
|
||||||
|
if (selectorAll.selectedOptions[0] === optionOfTheYear) {
|
||||||
|
advancedTypeShit.style.display = "inline";
|
||||||
|
selectorAll.style.display = "inline";
|
||||||
|
advancedTypeShit.addEventListener("input", haxxor);
|
||||||
|
} else {
|
||||||
|
advancedTypeShit.style.display = "none";
|
||||||
|
selectorAll.style.display = null;
|
||||||
|
advancedTypeShit.value = null;
|
||||||
|
advancedTypeShit.removeEventListener("input", haxxor);
|
||||||
|
}
|
||||||
|
});
|
||||||
const form = document.getElementById("only_form");
|
const form = document.getElementById("only_form");
|
||||||
form.addEventListener("submit", (e) => {
|
form.addEventListener("submit", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -189,11 +240,12 @@ const GETendp = (_) =>
|
|||||||
// damn
|
// damn
|
||||||
case 301:
|
case 301:
|
||||||
case 302:
|
case 302:
|
||||||
|
case 307:
|
||||||
|
case 308: // DONT EVER stick with 302
|
||||||
responsecontent = "redirect";
|
responsecontent = "redirect";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
htmlContent +=
|
htmlContent += `<tr>
|
||||||
`<tr>
|
|
||||||
<th>${key}</th>
|
<th>${key}</th>
|
||||||
<td><a href="${"./" + url}">${url}</a></td>
|
<td><a href="${"./" + url}">${url}</a></td>
|
||||||
<td>${responsecontent}</td>
|
<td>${responsecontent}</td>
|
||||||
@@ -203,6 +255,7 @@ const GETendp = (_) =>
|
|||||||
|
|
||||||
// htmlContent += "</tbody>";
|
// htmlContent += "</tbody>";
|
||||||
actualTableContent.innerHTML = htmlContent;
|
actualTableContent.innerHTML = htmlContent;
|
||||||
|
htmlContent = ''
|
||||||
})
|
})
|
||||||
.catch((e) => console.error(e));
|
.catch((e) => console.error(e));
|
||||||
|
|
||||||
@@ -25,7 +25,8 @@ body {
|
|||||||
grid-template-areas: "head head" "nav main" "nav foot";
|
grid-template-areas: "head head" "nav main" "nav foot";
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
body, html{
|
body,
|
||||||
|
html {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,17 +58,18 @@ nav {
|
|||||||
transition: height 1s ease-in-out, background-color 1s ease-in-out;
|
transition: height 1s ease-in-out, background-color 1s ease-in-out;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus{
|
&:focus,
|
||||||
|
&:has(a:active) {
|
||||||
height: 7em;
|
height: 7em;
|
||||||
background-color: paleturquoise;
|
background-color: paleturquoise;
|
||||||
transition: height 1s ease-in-out, background-color 1s ease-in-out;
|
transition: height 1s ease-in-out, background-color 1s ease-in-out;
|
||||||
}
|
}
|
||||||
> a {
|
> a {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +108,6 @@ footer {
|
|||||||
place-content: center;
|
place-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.box {
|
.box {
|
||||||
background-color: mistyrose;
|
background-color: mistyrose;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
@@ -117,9 +118,14 @@ footer {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
gap: 1em;
|
gap: 1em;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
> * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
form label,
|
form label,
|
||||||
input {
|
input,
|
||||||
|
select {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,14 +164,14 @@ textarea::placeholder {
|
|||||||
background-color: field;
|
background-color: field;
|
||||||
border: thin solid var(--dark-enough);
|
border: thin solid var(--dark-enough);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
/* width: max-content; */
|
width: fit-content;
|
||||||
max-height: 86vh;
|
max-height: 86vh;
|
||||||
outline: none;
|
outline: none;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
resize: none;
|
resize: none;
|
||||||
min-height: 16rem;
|
min-height: 16rem;
|
||||||
flex: 1 1 50%;
|
height:max-content;
|
||||||
}
|
}
|
||||||
/* ????? */
|
/* ????? */
|
||||||
|
|
||||||
@@ -176,16 +182,11 @@ img {
|
|||||||
|
|
||||||
.why {
|
.why {
|
||||||
min-width: 20rem;
|
min-width: 20rem;
|
||||||
/* padding: 4px; */
|
padding-inline: 4px;
|
||||||
max-width: 960px;
|
max-width: 960px;
|
||||||
|
|
||||||
min-height: 7rem;
|
min-height: 7rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.table > table {
|
.table > table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
@@ -206,3 +207,29 @@ td {
|
|||||||
/* selecting all cells using NOT & > * > * > * */
|
/* selecting all cells using NOT & > * > * > * */
|
||||||
padding: 3px 6px;
|
padding: 3px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 820px) {
|
||||||
|
body {
|
||||||
|
gap: 1em;
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-template-columns: auto;
|
||||||
|
grid-template-rows: auto;
|
||||||
|
grid-template-areas: "head " "nav" "main" "foot";
|
||||||
|
}
|
||||||
|
nav {
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
nav ul {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
nav li {
|
||||||
|
&:hover,
|
||||||
|
&:focus,
|
||||||
|
&:has(a:active) {
|
||||||
|
height: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user