pixel-battle/database/main.py

205 строки
5.8 KiB
Python

import config
from models import User, Pixel, RequestsFrequency
from psycopg import AsyncConnection
conninfo = 'host=%(host)s user=%(user)s password=%(password)s dbname=%(dbname)s' % {
'host': config.Database.host,
'user': config.Database.user,
'password': config.Database.password,
'dbname': config.Database.dbname,
}
async def get_user(
ip_address: str,
) -> list[Pixel]:
async with await AsyncConnection.connect(conninfo) as connection:
async with connection.cursor() as cursor:
sql = '''
select
users.id,
users.ip_address,
users.created,
count(history),
unnest(user_colors.color)
from
users
left outer join history on
users.id = history.user_id
left outer join user_colors on
users.id = user_colors.user_id
group by
users.id,
users.ip_address,
users.created;
'''
await cursor.execute(sql)
records = await cursor.fetchall()
return list(
Pixel(
x=pixel_x,
y=pixel_y,
color=pixel_color,
user=User(
id=user_id,
ip_address=user_ip_address,
progress=user_progress,
created=user_created,
),
last_update=pixel_last_update,
)
for
pixel_x,
pixel_y,
pixel_color,
user_id,
user_ip_address,
user_progress,
user_created,
pixel_last_update,
in
records
)
async def get_pixels() -> list[Pixel]:
async with await AsyncConnection.connect(conninfo) as connection:
async with connection.cursor() as cursor:
sql = '''
select
pixels.x,
pixels.y,
pixels.color,
pixels.last_update
from
pixels;
'''
await cursor.execute(sql)
records = await cursor.fetchall()
return list(
Pixel(
x=pixel_x,
y=pixel_y,
color=pixel_color,
last_update=pixel_last_update,
)
for
pixel_x,
pixel_y,
pixel_color,
pixel_last_update,
in
records
)
async def put_pixel(
x: int,
y: int,
color: int,
ip_address,
):
async with await AsyncConnection.connect(conninfo) as connection:
async with connection.cursor() as cursor:
sql = '''
call put_pixel(
%(x)s,
%(y)s,
%(color)s,
%(ip_address)s
);
'''
await cursor.execute(
sql,
{
'x': x,
'y': y,
'color': color,
'ip_address': ip_address,
},
)
async def get_requests_frequency(
ip_address: str,
) -> RequestsFrequency:
async with await AsyncConnection.connect(conninfo) as connection:
async with connection.cursor() as cursor:
sql = '''
select
count(requests_per_second),
count(requests_per_minute),
count(requests_per_hour),
count(requests_per_day)
from
requests
left join requests requests_per_second on
requests.id = requests_per_second.id and
requests_per_second.time > now() - '1 second'::interval
left join requests requests_per_minute on
requests.id = requests_per_minute.id and
requests_per_minute.time > now() - '1 minute'::interval
left join requests requests_per_hour on
requests.id = requests_per_hour.id and
requests_per_hour.time > now() - '1 hour'::interval
left join requests requests_per_day on
requests.id = requests_per_day.id and
requests_per_day.time > now() - '1 day'::interval
where
requests.ip_address = '91.195.204.120/32'::cidr;
'''
await cursor.execute(
sql,
{
'ip_address': ip_address,
},
)
requests_per_second, requests_per_minute, requests_per_hour, requests_per_day, = await cursor.fetchone()
return RequestsFrequency(
per_second=requests_per_second,
per_minute=requests_per_minute,
per_hour=requests_per_hour,
per_day=requests_per_day,
)
async def put_request(
ip_address: str,
method: str,
url: str,
is_secure: bool,
user_agent: str = None,
referer: str = None,
):
async with await AsyncConnection.connect(conninfo) as connection:
async with connection.cursor() as cursor:
sql = '''
insert into requests (
ip_address,
method,
url,
is_secure,
user_agent,
referer
) values (
%(ip_address)s,
%(method)s,
%(url)s,
%(is_secure)s,
%(user_agent)s,
%(referer)s
);
'''
await cursor.execute(
sql,
{
'ip_address': ip_address,
'method': method,
'url': url,
'is_secure': is_secure,
'user_agent': user_agent,
'referer': referer,
},
)