1
1
This repository has been archived on 2023-08-08. You can view files and clone it, but cannot push or open issues or pull requests.

123 lines
3.6 KiB
Python

import io
import string
import time
from random import SystemRandom
from typing import Self, Type
import pydantic
import telebot
from sqlalchemy.future import Engine
from .. import cryptography, database
class Account(pydantic.BaseModel):
name: str
login: str
passwd: str
@classmethod
def from_tuple(cls: Type[Self], tuple_: tuple[str, str, str]) -> Self:
return cls(name=tuple_[0], login=tuple_[1], passwd=tuple_[2])
def as_tuple(self: Self) -> tuple[str, str, str]:
return (self.name, self.login, self.passwd)
class _Accounts(pydantic.BaseModel):
accounts: list[Account] = pydantic.Field(default_factory=list)
def _accounts_list_to_json(accounts: list[tuple[str, str, str]]) -> str:
accounts = _Accounts(accounts=[Account.from_tuple(i) for i in accounts])
return accounts.json()
def json_to_accounts(json_: str) -> list[tuple[str, str, str]]:
accounts = _Accounts.parse_raw(json_)
return [i.as_tuple() for i in accounts.accounts]
Message = telebot.types.Message
def send_tmp_message(
bot: telebot.TeleBot, chat_id: telebot.types.Message, text: str, timeout: int = 5
) -> None:
bot_mes = bot.send_message(chat_id, text, parse_mode="MarkdownV2")
time.sleep(timeout)
bot.delete_message(chat_id, bot_mes.id)
def base_handler(
bot: telebot.TeleBot, mes: Message, prev_mes: Message | None = None
) -> None:
bot.delete_message(mes.chat.id, mes.id)
if prev_mes is not None:
bot.delete_message(prev_mes.chat.id, prev_mes.id)
def get_all_accounts(
engine: Engine, user_id: int, master_pass: str
) -> list[tuple[str, str, str]]:
accounts: list[tuple[str, str, str]] = []
for account_name in database.get.get_accounts(engine, user_id):
salt, enc_login, enc_passwd = database.get.get_account_info(
engine, user_id, account_name
)
login, passwd = cryptography.other_accounts.decrypt_account_info(
enc_login, enc_passwd, master_pass, salt
)
accounts.append((account_name, login, passwd))
return accounts
def accounts_to_json(accounts: list[tuple[str, str, str]]) -> io.StringIO:
file = io.StringIO(_accounts_list_to_json(accounts))
file.name = "passwords.json"
return file
def _base_check(val: str) -> bool:
"Returns false if finds new lines or backtick (`)"
return not ("\n" in val or "`" in val)
def check_account_name(name: str) -> bool:
"Returns true if account name is valid"
return _base_check(name)
def check_login(login: str) -> bool:
"Returns true if login is valid"
return _base_check(login)
def check_passwd(passwd: str) -> bool:
"Returns true if password is valid"
return _base_check(passwd)
def check_account(name: str, login: str, passwd: str) -> bool:
"""Runs checks for account name, login and password"""
return check_account_name(name) and check_login(login) and check_passwd(passwd)
def gen_passwd() -> str:
"""Generates password of length 32"""
choices = SystemRandom().choices
chars = frozenset(string.ascii_letters + string.digits + string.punctuation)
# Remove backtick and pipe characters and convert into tuple
chars = tuple(chars.difference("`|"))
while True:
passwd = "".join(choices(chars, k=32))
passwd_chars = frozenset(passwd)
# If there is at least one lowercase character, uppercase character
# and one punctuation character
if (
passwd_chars.intersection(string.ascii_lowercase)
and passwd_chars.intersection(string.ascii_uppercase)
and passwd_chars.intersection(string.punctuation)
):
return passwd