feed generation and accounts WIP
This commit is contained in:
4
notes.md
Normal file
4
notes.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
### Сомнения по API:
|
||||||
|
1) `feeds` API должно давать возможность получать инфу по ленте и ресетать ленту, вроде всё
|
||||||
|
2) Нужно ли API картинок? Вроде вообще всё будет делать scraper. (хотя наверное получение инфы о картинке по id нужная штука)
|
||||||
|
3) Возможно стоит добавить возможность динамической смены длины invite кода
|
||||||
@ -30,6 +30,13 @@ async def read_feed(
|
|||||||
)
|
)
|
||||||
feed.fill(feed_data)
|
feed.fill(feed_data)
|
||||||
|
|
||||||
|
groupname = get_groupname_by_feed_id(conn, feed_id)
|
||||||
|
if groupname is None:
|
||||||
|
return HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="No such feed",
|
||||||
|
)
|
||||||
|
|
||||||
if not check_membership_exists(conn, current_user.username, groupname) and current_user.role not in settings.settings.admin_roles:
|
if not check_membership_exists(conn, current_user.username, groupname) and current_user.role not in settings.settings.admin_roles:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_403_FORBIDDEN,
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
@ -39,21 +46,13 @@ async def read_feed(
|
|||||||
return feed
|
return feed
|
||||||
|
|
||||||
|
|
||||||
|
# maybe to delete
|
||||||
@feeds_router.post("/add")
|
@feeds_router.post("/add")
|
||||||
async def add_feed(
|
async def add_feed(
|
||||||
feed_id: int,
|
groupname: str,
|
||||||
picture_id: int,
|
|
||||||
value: int,
|
|
||||||
conn: Annotated[connection, Depends(get_db_connection)],
|
conn: Annotated[connection, Depends(get_db_connection)],
|
||||||
current_user: Annotated[User, Depends(get_current_user)]
|
current_user: Annotated[User, Depends(get_current_user)]
|
||||||
):
|
):
|
||||||
groupname = get_groupname_by_feed_id(conn, feed_id)
|
|
||||||
if groupname is None:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_404_NOT_FOUND,
|
|
||||||
detail="No such feed or feed is not linked to group",
|
|
||||||
)
|
|
||||||
|
|
||||||
group = Group()
|
group = Group()
|
||||||
group_data = get_group(conn, groupname)
|
group_data = get_group(conn, groupname)
|
||||||
if group_data is None:
|
if group_data is None:
|
||||||
@ -63,26 +62,50 @@ async def add_feed(
|
|||||||
)
|
)
|
||||||
group.fill(group_data)
|
group.fill(group_data)
|
||||||
|
|
||||||
if value == 0 and group.allow_skips is False:
|
if group.author != current_user.username and current_user.role not in settings.settings.admin_roles:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_403_FORBIDDEN,
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
detail="Skips are disallowed",
|
detail="Not allowed",
|
||||||
)
|
)
|
||||||
return db.create_feed(conn, current_user.username, feed_id, picture_id, value)
|
|
||||||
|
return db.create_feed(conn, groupname, []) # TODO: image list
|
||||||
|
|
||||||
|
|
||||||
|
# maybe to delete
|
||||||
@feeds_router.post("/delete")
|
@feeds_router.post("/delete")
|
||||||
async def delete_feed(
|
async def delete_feed(
|
||||||
username: str,
|
|
||||||
feed_id: int,
|
feed_id: int,
|
||||||
picture_id: int,
|
|
||||||
conn: Annotated[connection, Depends(get_db_connection)],
|
conn: Annotated[connection, Depends(get_db_connection)],
|
||||||
current_user: Annotated[User, Depends(get_current_user)]
|
current_user: Annotated[User, Depends(get_current_user)]
|
||||||
):
|
):
|
||||||
if current_user.role in settings.settings.admin_roles:
|
if current_user.role in settings.settings.admin_roles:
|
||||||
return db.delete_feed(conn, username, feed_id, picture_id)
|
return db.delete_feed(conn, feed_id)
|
||||||
else:
|
else:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_403_FORBIDDEN,
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
detail="Not allowed",
|
detail="Not allowed",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@feeds_router.post("/reset")
|
||||||
|
async def reset_feed(
|
||||||
|
groupname: str,
|
||||||
|
conn: Annotated[connection, Depends(get_db_connection)],
|
||||||
|
current_user: Annotated[User, Depends(get_current_user)]
|
||||||
|
):
|
||||||
|
group = Group()
|
||||||
|
group_data = get_group(conn, groupname)
|
||||||
|
if group_data is None:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="No such group",
|
||||||
|
)
|
||||||
|
group.fill(group_data)
|
||||||
|
|
||||||
|
if group.author != current_user.username and current_user.role not in settings.settings.admin_roles:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Not allowed",
|
||||||
|
)
|
||||||
|
|
||||||
|
return db.create_feed(conn, groupname, []) # TODO: image list
|
||||||
|
|||||||
@ -18,14 +18,12 @@ class User(BaseModel):
|
|||||||
self.password = params["password"]
|
self.password = params["password"]
|
||||||
self.role = params["role"]
|
self.role = params["role"]
|
||||||
self.disabled = params["disabled"]
|
self.disabled = params["disabled"]
|
||||||
self.groups_ids = params["groups_ids"]
|
|
||||||
self.last_seen_at = params["last_seen_at"]
|
self.last_seen_at = params["last_seen_at"]
|
||||||
self.created_at = params["created_at"]
|
self.created_at = params["created_at"]
|
||||||
username: str = ""
|
username: str = ""
|
||||||
password: str = ""
|
password: str = ""
|
||||||
role: str = "user"
|
role: str = "user"
|
||||||
disabled: bool = False
|
disabled: bool = False
|
||||||
groups_ids: list[str] | None = None
|
|
||||||
last_seen_at: datetime | None = None
|
last_seen_at: datetime | None = None
|
||||||
created_at: datetime | None = None
|
created_at: datetime | None = None
|
||||||
|
|
||||||
@ -98,3 +96,18 @@ class Feed(BaseModel):
|
|||||||
groupname: str = ""
|
groupname: str = ""
|
||||||
image_ids: list[int] = []
|
image_ids: list[int] = []
|
||||||
created_at: datetime | None = None
|
created_at: datetime | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class Account(BaseModel):
|
||||||
|
def fill(self, params):
|
||||||
|
self.id = params["id"]
|
||||||
|
self.platform = params["platform"]
|
||||||
|
self.login = params["login"]
|
||||||
|
self.metadata = params["metadata"]
|
||||||
|
self.created_at = params["created_at"]
|
||||||
|
id: int = -1
|
||||||
|
platform: str = ""
|
||||||
|
login: str = ""
|
||||||
|
password: str = ""
|
||||||
|
metadata: dict = {}
|
||||||
|
created_at: datetime | None = None
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from psycopg2._psycopg import connection
|
|||||||
|
|
||||||
def create_feed(
|
def create_feed(
|
||||||
conn: connection,
|
conn: connection,
|
||||||
groupname: int,
|
groupname: str,
|
||||||
image_ids: list[int]
|
image_ids: list[int]
|
||||||
):
|
):
|
||||||
with conn.cursor() as cur:
|
with conn.cursor() as cur:
|
||||||
@ -30,7 +30,7 @@ def delete_feed(
|
|||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
delete from picrinth.feeds
|
delete from picrinth.feeds
|
||||||
where feed_id = %s
|
where id = %s
|
||||||
""",
|
""",
|
||||||
(feed_id,),
|
(feed_id,),
|
||||||
)
|
)
|
||||||
@ -49,7 +49,7 @@ def get_feed(
|
|||||||
"""
|
"""
|
||||||
select groupname
|
select groupname
|
||||||
from picrinth.feeds
|
from picrinth.feeds
|
||||||
where feed_id = %s
|
where id = %s
|
||||||
""",
|
""",
|
||||||
(feed_id,),
|
(feed_id,),
|
||||||
)
|
)
|
||||||
@ -70,7 +70,7 @@ def get_groupname_by_feed_id(
|
|||||||
"""
|
"""
|
||||||
select groupname
|
select groupname
|
||||||
from picrinth.feeds
|
from picrinth.feeds
|
||||||
where feed_id = %s
|
where id = %s
|
||||||
""",
|
""",
|
||||||
(feed_id,),
|
(feed_id,),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -95,3 +95,16 @@ def get_picture_by_id(
|
|||||||
(id,),
|
(id,),
|
||||||
)
|
)
|
||||||
return cur.fetchone()
|
return cur.fetchone()
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_pictures_ids(
|
||||||
|
conn: connection,
|
||||||
|
):
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
select id
|
||||||
|
from picrinth.pictures
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
return [element for (element,) in cur.fetchall()]
|
||||||
|
|||||||
60
src/scraper/utils.py
Normal file
60
src/scraper/utils.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
from psycopg2._psycopg import connection
|
||||||
|
|
||||||
|
import db.pictures as db
|
||||||
|
from api.models import Account, Picture
|
||||||
|
from settings import startup_settings
|
||||||
|
from settings.consts import SUPPORTED_PLATFORMS
|
||||||
|
|
||||||
|
# TODO: rewrite mock functions to real ones
|
||||||
|
|
||||||
|
def generate_feed(
|
||||||
|
conn: connection,
|
||||||
|
accounts: list[Account]
|
||||||
|
):
|
||||||
|
for account in accounts:
|
||||||
|
if account.platform not in SUPPORTED_PLATFORMS:
|
||||||
|
raise Exception
|
||||||
|
# TODO: review typing
|
||||||
|
if account.platform not in startup_settings.platforms_enabled: # type: ignore
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
# TODO: Should get pictures from platforms APIs
|
||||||
|
match account.platform:
|
||||||
|
case "pinterest":
|
||||||
|
pinterest()
|
||||||
|
case "pixiv":
|
||||||
|
pixiv()
|
||||||
|
case "gelbooru":
|
||||||
|
gelbooru()
|
||||||
|
# TODO: remove mock results
|
||||||
|
pictures_ids = db.get_all_pictures_ids(conn)
|
||||||
|
return pictures_ids
|
||||||
|
|
||||||
|
|
||||||
|
def pinterest():
|
||||||
|
return
|
||||||
|
|
||||||
|
def pixiv():
|
||||||
|
return
|
||||||
|
|
||||||
|
def gelbooru():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def get_picture(
|
||||||
|
conn: connection,
|
||||||
|
picture_id: str
|
||||||
|
) -> int:
|
||||||
|
picture = Picture()
|
||||||
|
picture_data = db.get_picture_by_id(conn, picture_id)
|
||||||
|
if picture_id is None:
|
||||||
|
return -1
|
||||||
|
picture.fill(picture_data)
|
||||||
|
return picture.id
|
||||||
|
|
||||||
|
def get_credentials(
|
||||||
|
conn: connection,
|
||||||
|
platform: str,
|
||||||
|
groupname: str
|
||||||
|
) -> tuple[str, str]:
|
||||||
|
return 'a', 'b'
|
||||||
@ -1,5 +1,7 @@
|
|||||||
JOIN_CODE_SYMBOLS = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" # No O + 0, I + 1
|
JOIN_CODE_SYMBOLS = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" # No O + 0, I + 1
|
||||||
|
|
||||||
|
SUPPORTED_PLATFORMS = ["pinterest", "pixiv", "gelbooru"]
|
||||||
|
|
||||||
API_EDITABLE_SETTINGS_LIST = """
|
API_EDITABLE_SETTINGS_LIST = """
|
||||||
admin_roles ["admin"]
|
admin_roles ["admin"]
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
from consts import SUPPORTED_PLATFORMS
|
||||||
from decouple import config
|
from decouple import config
|
||||||
|
|
||||||
|
|
||||||
@ -19,6 +20,9 @@ algorithm = str(config("algorithm", "HS256"))
|
|||||||
access_token_expiration_time = int(config("access_token_expiration_time", default=10080))
|
access_token_expiration_time = int(config("access_token_expiration_time", default=10080))
|
||||||
|
|
||||||
# other settings
|
# other settings
|
||||||
|
join_code_length = int(config("join_code_length", default=8))
|
||||||
|
platforms_enabled = config("platforms_enabled", default=SUPPORTED_PLATFORMS, cast=list[str])
|
||||||
|
|
||||||
|
# dev
|
||||||
swagger_enabled = str_to_bool(str(config("swagger_enabled", "false")))
|
swagger_enabled = str_to_bool(str(config("swagger_enabled", "false")))
|
||||||
log_level = str(config("log_level", default="INFO"))
|
log_level = str(config("log_level", default="INFO"))
|
||||||
join_code_length = int(config("join_code_length", default=8))
|
|
||||||
|
|||||||
23
tables.sql
23
tables.sql
@ -59,11 +59,30 @@ create table picrinth.swipes (
|
|||||||
username text not null,
|
username text not null,
|
||||||
feed_id integer not null,
|
feed_id integer not null,
|
||||||
picture_id integer not null,
|
picture_id integer not null,
|
||||||
swipe_value smallint not null,
|
value smallint not null,
|
||||||
swiped_at timestamp with time zone default now(),
|
created_at timestamp with time zone default now(),
|
||||||
primary key (id),
|
primary key (id),
|
||||||
foreign key (username) references picrinth.users (username) on delete cascade on update cascade,
|
foreign key (username) references picrinth.users (username) on delete cascade on update cascade,
|
||||||
foreign key (feed_id) references picrinth.feeds (id) on delete cascade on update cascade,
|
foreign key (feed_id) references picrinth.feeds (id) on delete cascade on update cascade,
|
||||||
foreign key (picture_id) references picrinth.pictures (id) on delete cascade on update cascade,
|
foreign key (picture_id) references picrinth.pictures (id) on delete cascade on update cascade,
|
||||||
constraint swipes_unique unique (username, feed_id, picture_id)
|
constraint swipes_unique unique (username, feed_id, picture_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create table picrinth.accounts (
|
||||||
|
id serial not null,
|
||||||
|
platform text not null,
|
||||||
|
login text not null,
|
||||||
|
password text not null,
|
||||||
|
metadata jsonb null, -- meybe not needed
|
||||||
|
created_at timestamp with time zone default now(),
|
||||||
|
constraint unique_account_per_platform unique (platform, login)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table picrinth.group_accounts (
|
||||||
|
groupname text not null,
|
||||||
|
account_id int not null,
|
||||||
|
created_at timestamp with time zone default now(),
|
||||||
|
constraint unique_group_accounts unique (account_id, groupname)
|
||||||
|
foreign key (groupname) references picrinth.groups (groupname) on delete cascade on update cascade
|
||||||
|
foreign key (account_id) references picrinth.accounts (id) on delete cascade on update cascade
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user