├── .gitattributes
├── Dockerfile
├── update_translations.sh
├── bot
├── utils
│ ├── secret.example.py
│ ├── decode.py
│ ├── encode.py
│ ├── some_functions.py
│ ├── google_auth.py
│ └── sql.py
├── handlers
│ ├── bot_info.py
│ ├── errors.py
│ ├── admin_panel.py
│ ├── buttons.py
│ ├── reviews.py
│ ├── main_handlers.py
│ ├── decoding.py
│ ├── setup_gauth.py
│ └── encoding.py
├── aiogram_help
│ ├── states.py
│ ├── filters.py
│ └── keyboard_maker.py
├── middlewares
│ └── language_middleware.py
└── load_all.py
├── requirements.txt
├── env
├── bot internalisation.txt
├── mysql_data
└── init.sql
├── config.py
├── docker-compose.yml
├── installation.sh
├── app.py
├── .gitignore
├── README.md
├── locales
├── pcypher.pot
├── en
│ └── LC_MESSAGES
│ │ └── pcypher.po
├── ru
│ └── LC_MESSAGES
│ │ └── pcypher.po
└── uk
│ └── LC_MESSAGES
│ └── pcypher.po
└── LICENSE
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:latest
2 |
3 | RUN mkdir /src
4 | WORKDIR /src
5 | COPY requirements.txt /src/
6 | RUN pip install -r requirements.txt
7 | COPY . /src
--------------------------------------------------------------------------------
/update_translations.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | pybabel extract bot/ -o locales/pcypher.pot
3 | pybabel update -d locales -D pcypher -i locales/pcypher.pot
4 | pybabel compile -d locales -D pcypher
--------------------------------------------------------------------------------
/bot/utils/secret.example.py:
--------------------------------------------------------------------------------
1 | # This is just the example, but it works
2 |
3 |
4 | def key_func(__):
5 | return 13
6 |
7 |
8 | def key_func_back(master, code):
9 | code = int(code)
10 | return str(code // 13)
11 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | aiogram==2.6.1
2 | aiohttp==3.6.2
3 | aioredis==1.3.1
4 | async-timeout==3.0.1
5 | attrs==19.3.0
6 | Babel==2.8.0
7 | certifi==2019.11.28
8 | chardet==3.0.4
9 | hiredis==1.0.1
10 | idna==2.9
11 | multidict==4.7.4
12 | PyMySQL==0.9.3
13 | pyotp==2.3.0
14 | pypng==0.0.20
15 | PyQRCode==1.2.1
16 | pytz==2019.3
17 | yarl==1.4.2
18 |
--------------------------------------------------------------------------------
/env:
--------------------------------------------------------------------------------
1 | MYSQL_DATABASE=main
2 | MYSQL_USER=YOURMYSQLUSER
3 | MYSQL_ROOT_PASSWORD=SomeRootPassword
4 | MYSQL_PASSWORD=YOURMYSQLPASS
5 | BOT_TOKEN_CYPHER=123456:ABCDEfghjkLMNOPQ-RST
6 | BOT_HOST=PASTE.YOUR.IP_OR_DOMAIN.HERE
7 | BOT_PORT=5555
8 |
9 | # CHANGE THESE AND RENAME TO .env!!!!
10 | # FOR Webhook don't forget to open specified port and set up nginx.
--------------------------------------------------------------------------------
/bot/handlers/bot_info.py:
--------------------------------------------------------------------------------
1 | from aiogram import types
2 |
3 | from bot.load_all import dp, _
4 | from bot.utils.some_functions import increase_message_counter
5 |
6 |
7 | @dp.message_handler(commands=["info"])
8 | async def info(message: types.Message):
9 | increase_message_counter()
10 | await message.reply(_("https://telegra.ph/How-to-Use-Passcypher-Instruction-EN-06-02"))
11 |
--------------------------------------------------------------------------------
/bot/aiogram_help/states.py:
--------------------------------------------------------------------------------
1 | from aiogram.dispatcher.filters.state import State, StatesGroup
2 |
3 |
4 | class Encode(StatesGroup):
5 | MASTER_PASSWORD = State()
6 | PASSWORD = State()
7 | CODE = State()
8 |
9 |
10 | class Decode(StatesGroup):
11 | MASTER_PASSWORD = State()
12 | PASSWORD = State()
13 | CODE = State()
14 |
15 |
16 | class Other(StatesGroup):
17 | REVIEW = State()
18 |
19 |
20 | class GoogleAuth(StatesGroup):
21 | ONE = State()
22 | TWO = State()
23 |
--------------------------------------------------------------------------------
/bot internalisation.txt:
--------------------------------------------------------------------------------
1 | Internalize your bot
2 |
3 | FIRST TIME
4 | 1. pybabel extract bot/ -o locales/pcypher.pot
5 | 2. pybabel init -i locales/pcypher.pot -d locales -D pcypher -l en
6 | 3. pybabel init -i locales/pcypher.pot -d locales -D pcypher -l ru
7 | 4. pybabel init -i locales/pcypher.pot -d locales -D pcypher -l uk
8 | 5. pybabel compile -d locales -D pcypher
9 |
10 |
11 | UPDATING
12 | 1. pybabel extract bot/ -o locales/pcypher.pot
13 | 2. pybabel update -d locales -D pcypher -i locales/pcypher.pot
14 | 3. pybabel compile -d locales -D pcypher
15 |
--------------------------------------------------------------------------------
/mysql_data/init.sql:
--------------------------------------------------------------------------------
1 | CREATE DATABASE IF NOT EXISTS main;
2 | USE main;
3 | create table IF NOT EXISTS users
4 | (
5 | chat_id int not null,
6 | language varchar(4) null,
7 | id int auto_increment,
8 | date timestamp default CURRENT_TIMESTAMP not null,
9 | google varchar(1000) null,
10 | enabled int default 0 not null,
11 | blocked tinyint default 0 null,
12 | primary key (id, chat_id)
13 | );
14 | SET GLOBAL max_allowed_packet = 1024 * 1024 * 256;
--------------------------------------------------------------------------------
/bot/utils/decode.py:
--------------------------------------------------------------------------------
1 | from bot.utils.secret import key_func_back
2 | # Sorry for some obfuscation, but you'll easily reverse it if you want :)
3 |
4 |
5 | def decode(master, password, code):
6 | original_code = key_func_back(master, code)
7 |
8 | decoded = [password[0]]
9 | _i___ = 1
10 | i___ = 0
11 | for _i in range(len(original_code)):
12 | while i___ < _i___ + int(original_code[_i]):
13 | i___ += 1
14 | try:
15 | decoded.append(password[i___])
16 | except:
17 | break
18 | _i___ = i___ + 1
19 |
20 | return "".join(decoded)
21 |
--------------------------------------------------------------------------------
/bot/aiogram_help/filters.py:
--------------------------------------------------------------------------------
1 | from aiogram import types
2 | from aiogram.dispatcher.filters import BoundFilter
3 |
4 | from bot.load_all import _
5 | from config import admin_id
6 |
7 |
8 | class Buttons(BoundFilter):
9 | def __init__(self, key):
10 | self.key = key
11 |
12 | async def check(self, message: types.Message):
13 | return _(self.key) == message.text
14 |
15 |
16 | class IsAdmin(BoundFilter):
17 | admin_id = admin_id
18 |
19 | def __init__(self):
20 | pass
21 |
22 | async def check(self, message: types.Message):
23 | return message.chat.id == self.admin_id
24 |
--------------------------------------------------------------------------------
/bot/middlewares/language_middleware.py:
--------------------------------------------------------------------------------
1 | from aiogram.contrib.middlewares.i18n import I18nMiddleware
2 | from aiogram import types
3 | from config import I18N_DOMAIN, LOCALES_DIR
4 | from bot.utils.some_functions import sql
5 |
6 |
7 | def get_lang(chat_id):
8 | return sql.select(what="language", where="users", condition={"chat_id": chat_id})
9 |
10 |
11 | class ACLMiddleware(I18nMiddleware):
12 | """
13 | Modified i18n middleware
14 | """
15 |
16 | async def get_user_locale(self, action, args):
17 | user = types.User.get_current()
18 | return get_lang(user.id) or user.locale
19 |
20 |
21 | def setup_middleware(dp):
22 | i18n = ACLMiddleware(I18N_DOMAIN, LOCALES_DIR)
23 |
24 | dp.middleware.setup(i18n)
25 | return i18n
26 |
--------------------------------------------------------------------------------
/bot/load_all.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import logging
3 |
4 | from aiogram import Bot
5 | from aiogram import Dispatcher
6 | from aiogram.contrib.fsm_storage.redis import RedisStorage2
7 |
8 | from bot.middlewares.language_middleware import setup_middleware
9 | from config import TOKEN
10 |
11 | # from aiogram.contrib.fsm_storage.memory import MemoryStorage
12 |
13 | logging.basicConfig(format=u'%(filename)s [LINE:%(lineno)d] #%(levelname)-8s [%(asctime)s] %(message)s',
14 | level=logging.INFO)
15 | loop = asyncio.get_event_loop()
16 | # Set up storage (either in Redis or Memory)
17 | # storage = MemoryStorage()
18 | storage = RedisStorage2()
19 |
20 | bot = Bot(token=TOKEN, loop=loop, parse_mode="HTML")
21 | dp = Dispatcher(bot, storage=storage)
22 |
23 | # Setup i18n middleware
24 | i18n = setup_middleware(dp)
25 |
26 | # Alias for gettext method
27 | _ = i18n.gettext
28 |
--------------------------------------------------------------------------------
/config.py:
--------------------------------------------------------------------------------
1 | import os
2 | import secrets
3 | from pathlib import Path
4 |
5 | TOKEN = os.environ.get("BOT_TOKEN_CYPHER")
6 | sql_config = {
7 | "host": "127.0.0.1",
8 | "user": os.getenv("MYSQL_USER"),
9 | "password": os.getenv("MYSQL_PASSWORD"),
10 | "db": "main",
11 | "charset": 'utf8mb4'
12 | }
13 | I18N_DOMAIN = 'pcypher'
14 | BASE_DIR = Path(__file__).parent
15 | LOCALES_DIR = BASE_DIR / 'locales'
16 |
17 | Reviews_state = False
18 | # Set Reviews_state = True for enabling opportunity to leave reviews (probably not needed)
19 | review_channel = -1001443580761
20 | admin_id = 362089194
21 |
22 | Webhook_state = False
23 |
24 | # Set Webhook_state = True for enabling Webhook.
25 | WEBHOOK_PATH = f'/{secrets.token_urlsafe(128)}'
26 | WEBHOOK_HOST = os.environ.get("BOT_HOST")
27 | WEBHOOK_URL = f"https://{WEBHOOK_HOST}{WEBHOOK_PATH}/"
28 | WEBAPP_PORT = os.environ.get("BOT_PORT")
29 | WEBAPP_HOST = '127.0.0.1'
30 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.3'
2 | services:
3 |
4 | db:
5 | image: mysql:5.7
6 | container_name: database
7 | restart: always
8 | environment:
9 | MYSQL_DATABASE: 'main'
10 | ports:
11 | - '3306:3306'
12 | expose:
13 | - '3306'
14 | volumes:
15 | - my-db:/var/lib/mysql
16 |
17 | network_mode: "host"
18 |
19 | env_file:
20 | - ".env"
21 |
22 | redis:
23 | container_name: redis
24 | image: redis
25 | ports:
26 | - "6379:6379"
27 | volumes:
28 | - ../data/redis:/data
29 | entrypoint: redis-server --appendonly yes
30 | restart: always
31 |
32 | tgbot:
33 | container_name: pcypher
34 | build: .
35 | volumes:
36 | - .:/src
37 | command: python app.py
38 | restart: always
39 |
40 | network_mode: "host"
41 |
42 | env_file:
43 | - ".env"
44 |
45 |
46 | # Names our volume
47 | volumes:
48 | my-db:
--------------------------------------------------------------------------------
/installation.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | echo "Installing updates"
3 | sudo apt-get update
4 | sudo apt-get install \
5 | apt-transport-https \
6 | ca-certificates \
7 | curl \
8 | software-properties-common -y
9 | echo "Installing docker..."
10 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
11 | sudo apt-get update && sudo apt-get install docker-ce -y
12 | sudo curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose
13 | mv bot/utils/secret.example.py bot/utils/secret.py
14 |
15 | echo "Compiling languages..."
16 | pybabel extract bot/ -o locales/pcypher.pot
17 | pybabel init -i locales/pcypher.pot -d locales -D pcypher -l en
18 | pybabel init -i locales/pcypher.pot -d locales -D pcypher -l ru
19 | pybabel init -i locales/pcypher.pot -d locales -D pcypher -l uk
20 | pybabel compile -d locales -D pcypher
21 |
22 | echo "Starting bot..."
23 | sudo docker-compose up
24 |
--------------------------------------------------------------------------------
/bot/utils/encode.py:
--------------------------------------------------------------------------------
1 | from bot.utils.secret import key_func
2 | import random
3 | from bot.utils.some_functions import to_mix
4 | # Sorry for some obfuscation, but you'll easily reverse it if you want :)
5 |
6 |
7 | def char_mixer(____):
8 | _ = []
9 | _____ = []
10 | for i in range(len(____)):
11 | __ii__ = to_mix
12 | __i__ = ""
13 | _i_ = random.randint(1, 8)
14 | ___i__ = random.randint(0, 1)
15 | _.extend(str(_i_))
16 | for _iii_ in range(_i_):
17 | __i__ += __ii__[random.randint(1, len(__ii__)-1)]
18 | if ___i__:
19 | __i__ = __i__.upper()
20 | else:
21 | __i__ = __i__.lower()
22 | _____.append(f"{____[i]}{__i__}")
23 | return "".join(_____), int("".join(_))
24 |
25 |
26 | def code_lock(master_pass, raw_code):
27 |
28 | new_key = key_func(master_pass)
29 | locked_code = raw_code * new_key
30 | return locked_code
31 |
32 |
33 | def encode(to_encrypt, master_pass):
34 |
35 | result, raw_code = char_mixer(to_encrypt)
36 | code = code_lock(master_pass, raw_code)
37 |
38 | return result, code
39 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from asyncio import sleep
3 |
4 | from aiogram import executor
5 |
6 | from config import (WEBHOOK_URL, Reviews_state,
7 | Webhook_state, WEBAPP_HOST, WEBAPP_PORT)
8 | from bot.load_all import bot
9 |
10 |
11 | async def on_startup(dp):
12 | await on_startup_polling(dp)
13 | return await bot.set_webhook(url=WEBHOOK_URL)
14 |
15 |
16 | async def on_startup_polling(dp):
17 | from bot.utils.sql import sql
18 | logging.info(f"Wait 20 until MYSQL Starts... initialising MYSQL DATABASE")
19 | await sleep(20)
20 | with open("mysql_data/init.sql", "r") as file:
21 | command = file.read()
22 | if command:
23 | logging.info("Loaded SQL command")
24 | sql.execute(command)
25 | logging.info("Table created")
26 |
27 |
28 | if __name__ == '__main__':
29 | if Reviews_state:
30 | from bot.handlers.reviews import dp
31 | from bot.handlers.setup_gauth import dp
32 | from bot.handlers.bot_info import dp
33 | from bot.handlers.buttons import dp
34 | from bot.handlers.decoding import dp
35 | from bot.handlers.encoding import dp
36 | from bot.handlers.admin_panel import dp
37 | from bot.handlers.main_handlers import dp
38 | from bot.handlers.errors import dp
39 |
40 | if Webhook_state:
41 | executor.start_webhook(dispatcher=dp, webhook_path="",
42 | host=WEBAPP_HOST, port=WEBAPP_PORT, on_startup=on_startup)
43 | else:
44 | executor.start_polling(dp, on_startup=on_startup_polling)
45 |
--------------------------------------------------------------------------------
/bot/utils/some_functions.py:
--------------------------------------------------------------------------------
1 | from bot.utils.sql import sql
2 |
3 |
4 | def increase_message_counter(password=False):
5 | sql.update(table="Statistics", messages="`messages`+1", condition={"id": 0}, raw=True)
6 | if password:
7 | sql.update(table="Statistics", passwords="`passwords`+1", condition={"id": 0}, raw=True)
8 |
9 |
10 | def get_counters():
11 | users = sql.select(what="COUNT(*)", where="users")
12 | stats = sql.select(where="Statistics", what=["messages", "passwords"], condition={"id": 0})
13 | if stats:
14 | messages, passwords = stats[0]
15 | else:
16 | messages, passwords = 0, 0
17 | return {"users": users, "messages": messages, "passwords": passwords}
18 |
19 |
20 | allowed_chars = 'qwertyuiopasdfghjklzxcvbnm,.!£$%^&*()[];_-+1234567890йцукенгшщзхъфывапролджэячсмитьбю'
21 | to_mix = 'qwertyuiop asdfghjklzxcvbnm,.!£$%^&*()[];_-+1234567890 йцукенгшщзхъфывапролджэячсмитьбю'
22 |
23 |
24 | class OtherTexts:
25 | START = """----------------------------
26 | ENCRYPTION STARTS HERE
27 | ----------------------------
28 | """
29 | END = """
30 | ----------------------------
31 | ENCRYPTION ENDS HERE
32 | ----------------------------
33 | CODE
34 | """
35 | END_CODE = """
36 | ----------------------------"""
37 |
38 |
39 | def set_language(chat_id, lang):
40 | sql.update(table="users", language=lang, condition={"chat_id": chat_id})
41 |
42 |
43 | def check_if_new_user(chat_id):
44 | if not sql.select(where="users", condition={"chat_id": chat_id}):
45 | sql.insert(table="users", chat_id=chat_id)
46 |
--------------------------------------------------------------------------------
/bot/utils/google_auth.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import pyotp
4 | import pyqrcode
5 | import re
6 | from bot.utils.sql import sql
7 |
8 |
9 | def create_google_auth(chat_id: int):
10 | code = pyotp.random_base32()
11 | link = f"otpauth://totp/bot:{chat_id}@Passcypher?secret={code}&issuer=Passcypher"
12 | qr = pyqrcode.create(link, "L")
13 | name = f"code_{chat_id}.png"
14 | qr.png(name, scale=6)
15 | with open(name, "rb") as file:
16 | qr_code = file.read()
17 |
18 | os.remove(name)
19 |
20 | sql.update(table="users", google=code, enabled=1, condition={"chat_id": chat_id})
21 | return code, link, qr_code
22 |
23 |
24 | def enabled_g_auth(chat_id):
25 | return sql.select(what="enabled", where="users", condition={"chat_id": chat_id})
26 |
27 |
28 | def has_g_auth(chat_id):
29 | return sql.select(what="google", where="users", condition={"chat_id": chat_id})
30 |
31 |
32 | def verify(chat_id, code: str):
33 | if not code:
34 | return False
35 | secret = get_google_auth(chat_id)
36 | if not secret:
37 | return False
38 | totp = pyotp.TOTP(secret)
39 | code_regex = re.compile(r"^(\d{3}).?(\d{3})")
40 | code = code_regex.findall(code)
41 | if not code:
42 | return False
43 | code = "".join(*code)
44 | if not code:
45 | return False
46 | return totp.verify(code)
47 |
48 |
49 | def get_google_auth(chat_id):
50 | return sql.select(where="users",
51 | what="google",
52 | condition={"chat_id": chat_id})
53 |
54 |
55 | def insert_dash(line):
56 | return "-".join([line[i:i + 4] for i in range(0, len(line), 4)])
57 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 |
53 | # Django stuff:
54 | *.log
55 | local_settings.py
56 | db.sqlite3
57 |
58 | # Flask stuff:
59 | instance/
60 | .webassets-cache
61 |
62 | # Scrapy stuff:
63 | .scrapy
64 |
65 | # Sphinx documentation
66 | docs/_build/
67 |
68 | # PyBuilder
69 | target/
70 |
71 | # Jupyter Notebook
72 | .ipynb_checkpoints
73 |
74 | # pyenv
75 | .python-version
76 |
77 | # celery beat schedule file
78 | celerybeat-schedule
79 |
80 | # SageMath parsed files
81 | *.sage.py
82 |
83 | # Environments
84 | .env
85 | .venv
86 | env/
87 | venv/
88 | ENV/
89 | env.bak/
90 | venv.bak/
91 |
92 | # Spyder project settings
93 | .spyderproject
94 | .spyproject
95 |
96 | # Rope project settings
97 | .ropeproject
98 |
99 | # mkdocs documentation
100 | /site
101 |
102 | # mypy
103 | .mypy_cache/
104 |
105 | secret.py
106 | config_text.py
107 | .idea/
108 | config_test.py
109 |
--------------------------------------------------------------------------------
/bot/handlers/errors.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from bot.load_all import dp
3 |
4 |
5 | @dp.errors_handler()
6 | async def errors_handler(update, exception):
7 | """
8 | Exceptions handler. Catches all exceptions within task factory tasks.
9 | :param dispatcher:
10 | :param update:
11 | :param exception:
12 | :return: stdout logging
13 | """
14 | from aiogram.utils.exceptions import Unauthorized, InvalidQueryID, TelegramAPIError, \
15 | CantDemoteChatCreator, MessageNotModified, MessageToDeleteNotFound, MessageTextIsEmpty, RetryAfter, \
16 | CantParseEntities
17 |
18 | if isinstance(exception, CantDemoteChatCreator):
19 | logging.debug("Can't demote chat creator")
20 | return True
21 |
22 | if isinstance(exception, MessageNotModified):
23 | logging.debug('Message is not modified')
24 | return True
25 |
26 | if isinstance(exception, MessageToDeleteNotFound):
27 | logging.debug('Message to delete not found')
28 | return True
29 |
30 | if isinstance(exception, MessageTextIsEmpty):
31 | logging.debug('MessageTextIsEmpty')
32 | return True
33 |
34 | if isinstance(exception, Unauthorized):
35 | logging.info(f'Unauthorized: {exception}')
36 | return True
37 |
38 | if isinstance(exception, InvalidQueryID):
39 | logging.exception(f'InvalidQueryID: {exception} \nUpdate: {update}')
40 | return True
41 |
42 | if isinstance(exception, TelegramAPIError):
43 | logging.exception(f'TelegramAPIError: {exception} \nUpdate: {update}')
44 | return True
45 | if isinstance(exception, RetryAfter):
46 | logging.exception(f'RetryAfter: {exception} \nUpdate: {update}')
47 | return True
48 | if isinstance(exception, CantParseEntities):
49 | logging.exception(f'CantParseEntities: {exception} \nUpdate: {update}')
50 | return True
51 | logging.exception(f'Update: {update} \n{exception}')
52 |
--------------------------------------------------------------------------------
/bot/aiogram_help/keyboard_maker.py:
--------------------------------------------------------------------------------
1 | import typing
2 | from dataclasses import dataclass
3 |
4 | from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton
5 |
6 |
7 | @dataclass
8 | class ListOfButtons:
9 | text: typing.List
10 | callback: typing.List = None
11 | align: typing.List[int] = None
12 | """
13 | Использование:
14 | ListOfButtons(text=["Кнопка", "Кнопка", "Кнопка", "Кнопка"],
15 | callback=["callback1", "callback2", "callback3", "callback4"],
16 | align=[1, 2, 1]).keyboard
17 | row_sizes - количество кнопок в ряде
18 | """
19 |
20 | @property
21 | def inline_keyboard(self):
22 | return generate_inline_keyboard(self)
23 |
24 | @property
25 | def reply_keyboard(self):
26 | return generate_reply_keyboard(self)
27 |
28 |
29 | def generate_inline_keyboard(args: ListOfButtons) -> InlineKeyboardMarkup:
30 | keyboard = InlineKeyboardMarkup()
31 | if args.text and args.callback and not (len(args.text) == len(args.callback)):
32 | raise IndexError("Все списки должны быть одной длины!")
33 |
34 | if not args.align:
35 | for num, button in enumerate(args.text):
36 | keyboard.add(InlineKeyboardButton(text=str(button),
37 | callback_data=str(args.callback[num])))
38 | else:
39 | count = 0
40 | for row_size in args.align:
41 | keyboard.row(*[InlineKeyboardButton(text=str(text), callback_data=str(callback_data))
42 | for text, callback_data in
43 | tuple(zip(args.text, args.callback))[count:count + row_size]])
44 | count += row_size
45 | return keyboard
46 |
47 |
48 | def generate_reply_keyboard(args: ListOfButtons) -> ReplyKeyboardMarkup:
49 | keyboard = ReplyKeyboardMarkup(resize_keyboard=True)
50 |
51 | if not args.align:
52 | for num, button in enumerate(args.text):
53 | keyboard.add(KeyboardButton(text=str(button)))
54 | else:
55 | count = 0
56 | for row_size in args.align:
57 | keyboard.row(*[KeyboardButton(text=str(text)) for text in args.text[count:count + row_size]])
58 | count += row_size
59 | return keyboard
60 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Passcypher_bot
2 | Try this bot here: @pcypher_bot
3 |
4 |
5 | This bot will help you encrypt your passwords to store them in Telegram (or wherever you want)
6 | Also you can encrypt and decrypt your txt files.
7 | However, don't put large txt files, please.
8 |
9 | This repository is created to show that bot does not store your passwords locally, and also you can make your commits to improve it.
10 |
11 | New instruction:
12 | https://telegra.ph/How-to-Use-Passcypher-Instruction-EN-06-02
13 | One more link is the instruction for Google Authenticator!
14 | https://telegra.ph/Passcypher-Google-Authenticator-06-02
15 |
16 | # New Massive Update 28/07/2019
17 | You can create your bot with just one command! Docker included!
18 |
19 | # New Features 12/07/2019
20 | 1. Added support i18n for translations
21 | 2. Made the use of standard filters of aiogram
22 |
23 |
24 |
25 | # New Features
26 | 1. Updated to aiogram 2.0
27 | 2. Stated modified
28 | 3. Handlers separated
29 | 4. Statistics command
30 | 5. Use polling instead of Webhook
31 | 6. Added Ukrainian language
32 | 7. Bot now deletes user messages with passwords!
33 |
34 | # Google Authenticator
35 |
36 | Google authenticator feature has been added, so you won't need to enter your master password every time,
37 | but instead, you'll be able to use Google authenticator app to unlock your passwords.
38 |
39 |
40 | Download it here:
41 | App store link https://itunes.apple.com/gb/app/google-authenticator/id388497605?mt=8
42 |
43 | Android link https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en_GB
44 |
45 | # How to use (WEBHOOK for advanced usage)
46 |
47 | 1. Clone the repository
48 | 2. Amend env file and rename to .env
49 | 3. Amend the config.py:
50 | - Change the Webhook state to True
51 | 4. Set up nginx redirection (and open port for the app)
52 | 5. Run sudo bash installation.sh
53 |
54 |
55 | # How to use (POLLING)
56 |
57 | 1. Clone the repository
58 | 2. Amend env file and rename to .env
59 | 3. Run sudo bash installation.sh
60 |
61 |
62 | After the bot successfully started press `Ctrl+Z` to exit docker console
63 |
64 | Whenever you want to enter it, go to the directory and enter `docker-compose up`
65 |
66 | To stop the docker, enter `docker-compose down` or press `Ctrl+C` if you're inside.
67 |
--------------------------------------------------------------------------------
/bot/handlers/admin_panel.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import re
3 | from asyncio import sleep
4 |
5 | from aiogram import types
6 | from aiogram.utils.exceptions import BotBlocked, ChatNotFound, UserDeactivated
7 |
8 | from bot.load_all import bot, dp
9 | from bot.aiogram_help.filters import IsAdmin, admin_id
10 | from bot.utils.some_functions import increase_message_counter, sql
11 |
12 |
13 | @dp.message_handler(IsAdmin(), commands=["send_to_all_ru",
14 | "send_to_all_en",
15 | "send_to_all_uk"])
16 | async def encode_m(message: types.Message):
17 | increase_message_counter()
18 |
19 | result = await sender(message)
20 | await message.reply(f"Заблокировано {result}")
21 |
22 |
23 | @dp.message_handler(IsAdmin(), commands=["check_blocked"])
24 | async def encode_m(message: types.Message):
25 | increase_message_counter()
26 | await checker()
27 |
28 |
29 | async def sender(message: types.Message):
30 | command = re.match(r"(/send_to_all_(\w\w))", message.text)
31 | lang = command.group(2)
32 | text = message.text.split(command.group(1))[1]
33 | if not text:
34 | return 0
35 |
36 | users_list = sql.select(what="chat_id", where="users", condition={"language": lang,
37 | "blocked": 0})
38 | total_users = len(users_list)
39 | to_edit = await bot.send_message(admin_id, f"Всего живых {total_users}. Послано 0 Юзерам. Текст:{text}")
40 | errors = 0
41 | count = 0
42 | for (user,) in users_list:
43 | try:
44 | await bot.send_message(chat_id=user, text=text)
45 |
46 | except (BotBlocked, ChatNotFound, UserDeactivated):
47 | sql.update(table="users", condition={"chat_id": user}, blocked=1)
48 | logging.info(f"User {user} blocked bot")
49 | errors += 1
50 |
51 | except Exception as err:
52 | logging.error(err)
53 | finally:
54 | await sleep(0.04)
55 | count += 1
56 | if count % 10 == 0:
57 | await to_edit.edit_text(f"Всего {total_users}. Послано {count} Юзерам.")
58 | return errors
59 |
60 |
61 | async def checker():
62 |
63 | users_list = sql.select(what="chat_id", where="users", condition={"blocked": 0})
64 | total_users = len(users_list)
65 | to_edit = await bot.send_message(admin_id, f"Всего {total_users} юзеров.")
66 | count = 0
67 | for (user,) in users_list:
68 | try:
69 | await bot.send_chat_action(chat_id=user, action=types.chat.ChatActions.TYPING)
70 |
71 | except (BotBlocked, ChatNotFound, UserDeactivated):
72 |
73 | sql.update(table="users", condition={"chat_id": user}, blocked=1)
74 | logging.info(f"User {user} blocked bot")
75 | count += 1
76 | finally:
77 | await sleep(0.4)
78 |
79 | await to_edit.edit_text(f"Всего живых {total_users}. Заблокировано {count} Юзеров.")
80 |
--------------------------------------------------------------------------------
/bot/handlers/buttons.py:
--------------------------------------------------------------------------------
1 | from aiogram import types
2 | from aiogram.dispatcher import FSMContext
3 |
4 | from bot.load_all import bot, dp, _
5 | from bot.aiogram_help.filters import Buttons
6 | from bot.aiogram_help.states import Encode
7 | from bot.utils.google_auth import enabled_g_auth, get_google_auth, has_g_auth
8 | from bot.utils.some_functions import increase_message_counter
9 | from bot.aiogram_help.keyboard_maker import ListOfButtons
10 | from bot.utils.some_functions import allowed_chars
11 |
12 |
13 | @dp.message_handler(Buttons("🔒 Encode"))
14 | async def encode_m(message: types.Message, state: FSMContext):
15 | increase_message_counter()
16 |
17 | chat_id = message.chat.id
18 | if not enabled_g_auth(chat_id):
19 | await bot.send_message(chat_id, _("""
20 | Please enter your master password.
21 | You can make everything faster with Google Authenticator!
22 | Press /g_auth_info
23 |
24 | """))
25 | await Encode.MASTER_PASSWORD.set()
26 | else:
27 | await state.update_data(master_pass=get_google_auth(chat_id))
28 | await Encode.PASSWORD.set()
29 | await bot.send_message(chat_id, _("""Enter phrase you want to encrypt.
30 | It should be under 400 characters, for best results there should be only characters from this list:
31 |
{allowed_chars}
32 | THE BOT DELETES YOUR MESSAGES WITH PASSWORDS AFTER 10 SECONDS
33 | """).format(allowed_chars=allowed_chars))
34 |
35 |
36 | @dp.message_handler(Buttons("🔑 Decode"))
37 | async def decode_m(message: types.Message):
38 | increase_message_counter()
39 |
40 | await message.reply(_("https://telegra.ph/Passwords-Decryption-Process-06-02"))
41 |
42 |
43 | @dp.message_handler(Buttons("ℹ️How to use"))
44 | async def info_m(message: types.Message):
45 | increase_message_counter()
46 | await message.reply(_("https://telegra.ph/How-to-Use-Passcypher-Instruction-EN-06-02"))
47 |
48 |
49 | @dp.message_handler(Buttons("🇬🇧 Set language"))
50 | async def language_set(message: types.Message):
51 | increase_message_counter()
52 |
53 | chat_id = message.chat.id
54 | await bot.send_message(chat_id,
55 | _("""
56 | Hello, {}
57 | Let's choose your language
58 | """).format(message.from_user.first_name),
59 | reply_markup=ListOfButtons(
60 | text=["English", "Русский", "Українська"],
61 | callback=["language en", "language ru", "language uk"]
62 | ).inline_keyboard)
63 |
64 |
65 | @dp.message_handler(Buttons("🔐 Two step verification"))
66 | async def set_google_auth(message: types.Message):
67 | increase_message_counter()
68 | chat_id = message.chat.id
69 | text = _("https://telegra.ph/Passcypher-Google-Authenticator-06-02") + "\n\n"
70 | if has_g_auth(chat_id):
71 | if enabled_g_auth(chat_id):
72 | await bot.send_message(chat_id,
73 | text + _("Here you can enable and disable your Google Authenticator settings"),
74 | reply_markup=ListOfButtons(
75 | text=[_("Turn off")],
76 | callback=["turn 0"]).inline_keyboard)
77 | else:
78 |
79 | await bot.send_message(chat_id,
80 | text + _("Here you can enable and disable your Google Authenticator settings"),
81 | reply_markup=ListOfButtons(
82 | text=[_("Turn on")],
83 | callback=["turn 1"]).inline_keyboard)
84 | else:
85 | await bot.send_message(chat_id, _("Google Authenticator is not set for you. Press /g_auth_info"))
86 |
--------------------------------------------------------------------------------
/bot/handlers/reviews.py:
--------------------------------------------------------------------------------
1 | from aiogram import types
2 | from aiogram.dispatcher import FSMContext
3 |
4 | import config
5 | from bot.load_all import bot, dp, logging, _
6 | from bot.aiogram_help.filters import Buttons
7 | from bot.aiogram_help.states import Other
8 | from bot.utils.some_functions import increase_message_counter
9 | from bot.aiogram_help.keyboard_maker import ListOfButtons
10 |
11 |
12 | @dp.message_handler(Buttons("📝 Write a review"))
13 | async def reviews_button(message: types.Message):
14 | increase_message_counter()
15 |
16 | chat_id = message.chat.id
17 | await bot.send_message(chat_id, _("""Please, it is important for me to receive a response and advice from you.
18 | How would you change the bot? Any comments are appreciated.
19 |
20 | Your comment will be posted anonymously in our channel @pcypher
21 | Or you can just rate the bot using this link: https://t.me/pcypher/16
22 | """),
23 | reply_markup=ListOfButtons(
24 | text=[_("Give an advice to the bot")],
25 | callback=["give_advice"]
26 | ).inline_keyboard)
27 |
28 |
29 | @dp.callback_query_handler(text="give_advice")
30 | async def give_advice(call: types.CallbackQuery, state: FSMContext):
31 | chat_id = call.message.chat.id
32 | await Other.REVIEW.set()
33 | await bot.edit_message_reply_markup(chat_id, call.message.message_id)
34 | last_message = await bot.send_message(chat_id, _("""
35 | Your advice:
36 |
37 | {advice}
38 |
39 | Write your advice in the next message.
40 | """).format(advice=" "),
41 | reply_markup=ListOfButtons(
42 | text=[_("Cancel")],
43 | callback=["cancel"]
44 | ).inline_keyboard)
45 | await state.update_data(last_message=last_message.message_id)
46 |
47 |
48 | @dp.message_handler(state=Other.REVIEW)
49 | async def your_advice(message: types.Message, state: FSMContext):
50 | chat_id = message.chat.id
51 | try:
52 | last_message = (await state.get_data()).get("last_message")
53 | await bot.edit_message_reply_markup(chat_id, last_message)
54 | except Exception as e:
55 | logging.error(f"{e}")
56 | await state.update_data(advice=message.text)
57 | last_message = await bot.send_message(chat_id, _("""
58 | Your advice:
59 |
60 | {advice}
61 |
62 | Write your advice in the next message.
63 | """).format(advice=message.text),
64 | reply_markup=ListOfButtons(
65 | text=[
66 | _("Publish"),
67 | _("Cancel")],
68 | callback=[
69 | "publish",
70 | "cancel"]
71 | ).inline_keyboard)
72 |
73 | await state.update_data(last_message=last_message.message_id)
74 |
75 |
76 | @dp.callback_query_handler(state=Other.REVIEW)
77 | async def cancel_or_publish(call: types.CallbackQuery, state: FSMContext):
78 | chat_id = call.message.chat.id
79 |
80 | try:
81 | last_message = (await state.get_data()).get("last_message")
82 | await bot.edit_message_reply_markup(chat_id, last_message)
83 | except Exception as e:
84 | logging.error(f"{e}")
85 |
86 | if call.data == "cancel":
87 | await bot.send_message(chat_id, _("Cancelled"))
88 | await state.finish()
89 | return
90 | elif call.data == "publish":
91 | advice = (await state.get_data()).get("advice")
92 | await bot.send_message(config.review_channel, _("""
93 | #Reviews Post:
94 |
95 | {}
96 | """).format(advice))
97 |
--------------------------------------------------------------------------------
/bot/handlers/main_handlers.py:
--------------------------------------------------------------------------------
1 | from aiogram import types
2 | from aiogram.dispatcher.dispatcher import FSMContext
3 | from aiogram.utils.exceptions import CantParseEntities, MessageNotModified
4 |
5 | from bot.load_all import bot, dp, _
6 | from bot.utils.some_functions import increase_message_counter, get_counters, check_if_new_user, set_language
7 | from bot.aiogram_help.keyboard_maker import ListOfButtons
8 |
9 |
10 | @dp.message_handler(commands=["start"], state="*")
11 | async def starting(message: types.Message, state: FSMContext):
12 | increase_message_counter()
13 | await state.reset_state()
14 | chat_id = message.chat.id
15 | check_if_new_user(chat_id)
16 |
17 | menu = ListOfButtons(
18 | text=[_("🔒 Encode"),
19 | _("🔑 Decode"),
20 | _("ℹ️How to use"),
21 | _("🇬🇧 Set language"),
22 | _("🔐 Two step verification"),
23 | _("📝 Write a review")],
24 | align=[2, 2, 2]
25 | ).reply_keyboard
26 |
27 | await bot.send_message(chat_id,
28 | _("""
29 | Hello, {}
30 | This bot is designed to encrypt your passwords so you can store them publicly, for example in your \
31 | Telegram saved messages.
32 |
33 | You can choose your language using command /set_language
34 | """).format(message.from_user.first_name),
35 | reply_markup=menu)
36 |
37 |
38 | @dp.callback_query_handler(text_contains="language")
39 | async def change_language(call: types.CallbackQuery, state: FSMContext):
40 | chat_id = call.message.chat.id
41 | try:
42 | await bot.edit_message_reply_markup(chat_id, call.message.message_id, reply_markup=None)
43 | except MessageNotModified:
44 | pass
45 | language = call.data.split()[1]
46 | set_language(chat_id, language)
47 | menu = ListOfButtons(
48 | text=[_("🔒 Encode", locale=language),
49 | _("🔑 Decode", locale=language),
50 | _("ℹ️How to use", locale=language),
51 | _("🇬🇧 Set language", locale=language),
52 | _("🔐 Two step verification", locale=language),
53 | _("📝 Write a review", locale=language)],
54 | align=[2, 2, 2]
55 | ).reply_keyboard
56 |
57 | await bot.send_message(chat_id, _("""Language has changed to 🇬🇧EN
58 |
59 | {users} users are using this bot.
60 |
61 | {passwords} passwords encrypted.
62 | {messages} messages received.
63 |
64 | Start using this bot: /info""", locale=language).format(**get_counters()),
65 | reply_markup=menu)
66 |
67 |
68 | @dp.message_handler(commands=["statistics"])
69 | async def statistics(message: types.Message):
70 | chat_id = message.chat.id
71 | await bot.send_message(chat_id, _("""
72 | {users} users are using this bot.
73 |
74 | {passwords} passwords encrypted.
75 | {messages} messages received.
76 | """).format(**get_counters()))
77 |
78 |
79 | @dp.message_handler(commands=["set_language"])
80 | async def lang_choose(message: types.Message):
81 | chat_id = message.chat.id
82 |
83 | increase_message_counter()
84 | try:
85 | await bot.send_message(chat_id,
86 | _("""
87 | Hello, {}
88 | Firstly, let's choose your language
89 | """).format(message.from_user.first_name),
90 | reply_markup=ListOfButtons(
91 | text=["English", "Русский", "Українська"],
92 | callback=["language en", "language ru", "language uk"]
93 | ).inline_keyboard)
94 | except CantParseEntities as err:
95 | print(f"Error. CantParseEntities: {err}")
96 |
97 |
98 | @dp.message_handler(content_types=types.ContentType.TEXT)
99 | async def unknown(message: types.Message, state: FSMContext):
100 | increase_message_counter()
101 |
102 | text = (_("🔒 Encode") + f" '{message.text}'")[:20] + "..."
103 |
104 | await message.reply(_("""
105 | Looks like the input is invalid...
106 | To decode your password - forward the message with encoded password you received from bot.
107 | ᅠ
108 | Perhaps you wanted to encrypt this message? Click """) + _("🔒 Encode") +
109 | _("\n\nOr setup the language again /set_language"),
110 | reply_markup=ListOfButtons(
111 | text=[text],
112 | callback=[f"encrypt_saved"]
113 | ).inline_keyboard)
114 |
115 |
116 | @dp.message_handler(state="*")
117 | async def unknown_message(message: types.Message, state: FSMContext):
118 | await message.reply(_("Seems like you have an unfinished business..."))
119 |
120 |
121 | @dp.callback_query_handler(state="*")
122 | async def unknown_message(call: types.CallbackQuery, state: FSMContext):
123 | await call.answer(_("Seems like you have an unfinished business..."))
124 |
--------------------------------------------------------------------------------
/bot/handlers/decoding.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import binascii
3 | import re
4 |
5 | from aiogram import types
6 | from aiogram.dispatcher import FSMContext
7 | from aiogram.utils.exceptions import BadRequest
8 |
9 | from bot.load_all import bot, dp, _
10 | from bot.aiogram_help.states import Decode
11 | from bot.utils.decode import decode
12 | from bot.utils.google_auth import enabled_g_auth, get_google_auth, has_g_auth, verify
13 | from bot.utils.some_functions import increase_message_counter
14 | from bot.utils.some_functions import OtherTexts
15 |
16 |
17 | @dp.message_handler(regexp="ENCRYPTION STARTS HERE")
18 | async def decode_start(message: types.Message, state: FSMContext):
19 | increase_message_counter()
20 | chat_id = message.chat.id
21 | text = message.text
22 | expression = re.compile(f"{OtherTexts.START}(.*){OtherTexts.END}")
23 | try:
24 | extract_encoded = expression.findall(text)[0]
25 |
26 | except IndexError:
27 | await bot.send_message(chat_id, _("Error. Wrong file"))
28 | return
29 | expression = re.compile(f"{OtherTexts.END}(.*){OtherTexts.END_CODE}")
30 | code = expression.findall(text)[0]
31 |
32 | await state.update_data(password=extract_encoded, code=code)
33 | if not enabled_g_auth(chat_id):
34 | await bot.send_message(chat_id, _("""
35 | Please enter your master password.
36 | You can make everything faster with Google Authenticator!
37 | Press /g_auth_info
38 |
39 | """))
40 | else:
41 | await bot.send_message(chat_id, _("Enter the code from the app"))
42 | await Decode.MASTER_PASSWORD.set()
43 |
44 |
45 | @dp.message_handler(regexp="#encoded_pass")
46 | async def decode_start(message: types.Message, state: FSMContext):
47 | increase_message_counter()
48 | chat_id = message.chat.id
49 | enc = message.text.replace("\n", " ")
50 | try:
51 | encoded = re.findall("#encoded_pass: '(.*)'.*#", enc)[0]
52 | code = re.findall("#key: '(.*)'", enc)[0]
53 | except IndexError:
54 | await bot.send_message(chat_id, _("Error"))
55 | return
56 | await state.update_data(password=encoded, code=code)
57 | if not enabled_g_auth(chat_id):
58 | await bot.send_message(chat_id, _("""
59 | Please enter your master password.
60 | You can make everything faster with Google Authenticator!
61 | Press /g_auth_info
62 |
63 | """))
64 | else:
65 | await bot.send_message(chat_id, _("Enter the code from the app"))
66 | await Decode.MASTER_PASSWORD.set()
67 |
68 |
69 | @dp.message_handler(content_types=types.ContentType.DOCUMENT)
70 | async def decode_start(message: types.Message, state: FSMContext):
71 | increase_message_counter()
72 | chat_id = message.chat.id
73 | file_id = message.document.file_id
74 | try:
75 | await bot.download_file_by_id(file_id, "to_decode.txt")
76 | except BadRequest:
77 | return await message.reply(_("INVALID FILE"))
78 | with open("to_decode.txt", "r") as file:
79 | try:
80 | text = file.read()
81 | except UnicodeDecodeError:
82 | await bot.send_message(chat_id, _("INVALID FILE"))
83 | return
84 | expression = re.compile(f"{OtherTexts.START}(.*){OtherTexts.END}")
85 | try:
86 | extract_encoded = expression.findall(text)[0]
87 |
88 | except IndexError:
89 | await bot.send_message(chat_id, _("Error. Wrong file"))
90 | return
91 | expression = re.compile(f"{OtherTexts.END}(.*){OtherTexts.END_CODE}")
92 | code = expression.findall(text)[0]
93 | await state.update_data(password=extract_encoded, code=code, doc=True)
94 |
95 | if not enabled_g_auth(chat_id):
96 | await bot.send_message(chat_id, _("""
97 | Please enter your master password.
98 | You can make everything faster with Google Authenticator!
99 | Press /g_auth_info
100 |
101 | """))
102 | else:
103 | await bot.send_message(chat_id, _("Enter the code from the app"))
104 | await Decode.MASTER_PASSWORD.set()
105 |
106 | await asyncio.sleep(10)
107 | await message.delete()
108 |
109 |
110 | @dp.message_handler(commands=["cancel"], state=Decode.MASTER_PASSWORD)
111 | async def decode_1(message: types.Message, state: FSMContext):
112 | await message.answer("OK.")
113 | await state.reset_state()
114 |
115 |
116 | @dp.message_handler(state=Decode.MASTER_PASSWORD)
117 | async def decode_1(message: types.Message, state: FSMContext):
118 | increase_message_counter()
119 |
120 | chat_id = message.chat.id
121 | en_password = (await state.get_data()).get("password")
122 | code = (await state.get_data())["code"]
123 | if not enabled_g_auth(chat_id):
124 | master = message.text
125 | else:
126 | if not has_g_auth(chat_id):
127 | await message.reply(_("An error has occurred, you lost the Google authenticator settings\n"
128 | "Please re-configure it once again /g_auth_info"))
129 | await state.finish()
130 |
131 | return
132 | try:
133 | if verify(chat_id, message.text):
134 | master = get_google_auth(chat_id)
135 | else:
136 | await bot.send_message(chat_id, _("Code is incorrect, try again or /cancel"))
137 | return
138 | except binascii.Error:
139 | await bot.send_message(chat_id, _("Code is incorrect, try again or /cancel"))
140 | return
141 |
142 | password = (decode(master, en_password, code)).replace("\\n", "\n")
143 |
144 | if (await state.get_data()).get("doc"):
145 |
146 | with open("decoded.txt", "w") as file:
147 | file.write(password.replace("\\n", "\n"))
148 | await bot.send_document(chat_id, open("decoded.txt", "rb"))
149 | with open("decoded.txt", "w") as file:
150 | file.write(" ")
151 | else:
152 | await bot.send_message(chat_id, _("""
153 | Your decoded password is inside citation marks '{password}'""").format(
154 | password=password
155 | ))
156 | await state.finish()
157 |
158 | await asyncio.sleep(10)
159 | await message.delete()
160 |
--------------------------------------------------------------------------------
/bot/handlers/setup_gauth.py:
--------------------------------------------------------------------------------
1 | import binascii
2 |
3 | from aiogram import types
4 | from aiogram.dispatcher import FSMContext
5 |
6 | from bot.load_all import bot, dp, logging, _
7 | from bot.aiogram_help.states import GoogleAuth
8 | from bot.utils.google_auth import has_g_auth, enabled_g_auth, verify, create_google_auth
9 | from bot.utils.some_functions import increase_message_counter, sql
10 | from bot.aiogram_help.keyboard_maker import ListOfButtons
11 |
12 |
13 | @dp.message_handler(commands=["g_auth_info"])
14 | async def info(message: types.Message):
15 | increase_message_counter()
16 | chat_id = message.chat.id
17 | text = _(
18 | "To encrypt your phrase/file you need to enter a master password each time you want to encrypt or decrypt, or"
19 | " you can enable Google Authenticator and enter one-time codes from your phone only to decrypt"
20 | " your passwords. \n"
21 | "(Master password will be kept in database then) \n\n"
22 | "Please make your choice (you can change it later with command /reset_google_auth\n")
23 | await bot.send_message(chat_id, text, reply_markup=ListOfButtons(
24 | text=[_("Setup")],
25 | callback=["g_auth_setup"]).inline_keyboard)
26 |
27 |
28 | @dp.message_handler(commands=["reset_google_auth"])
29 | async def info(message: types.Message):
30 | increase_message_counter()
31 | chat_id = message.chat.id
32 | if has_g_auth(chat_id):
33 | text = _("Here you can enable and disable your Google Authenticator settings")
34 | if enabled_g_auth(chat_id):
35 | await bot.send_message(chat_id, text,
36 | reply_markup=ListOfButtons(
37 | text=[_("Turn off")],
38 | callback=["turn 0"]).inline_keyboard)
39 | else:
40 |
41 | await bot.send_message(chat_id, text,
42 | reply_markup=ListOfButtons(
43 | text=[_("Turn on")],
44 | callback=["turn 1"]).inline_keyboard)
45 | else:
46 | await bot.send_message(chat_id, _("Google Authenticator is not set for you. Press /g_auth_info"))
47 |
48 |
49 | @dp.callback_query_handler(text_contains="turn")
50 | async def g_auth(call: types.CallbackQuery, state: FSMContext):
51 | chat_id = call.message.chat.id
52 | enabled = call.data.split()[1]
53 | sql.update(table="users", enabled=enabled, condition={"chat_id": chat_id})
54 | try:
55 | await bot.edit_message_text(text=_("That is done"),
56 | chat_id=chat_id,
57 | message_id=call.message.message_id)
58 | except Exception as e:
59 | logging.error(f"{e}")
60 |
61 |
62 | @dp.callback_query_handler(text="g_auth_setup")
63 | async def g_auth(call: types.CallbackQuery, state: FSMContext):
64 | chat_id = call.message.chat.id
65 | try:
66 | await bot.edit_message_reply_markup(chat_id, message_id=call.message.message_id)
67 | except Exception as e:
68 | logging.error(f"{e}")
69 |
70 | if has_g_auth(chat_id):
71 | await bot.send_message(chat_id, _("You have already received the Google Authenticator code"))
72 | return
73 |
74 | await bot.send_message(chat_id, _("""
75 | Please ensure you have the app installed.
76 | IOS
77 | Android
78 |
79 | Press continue when you done. After you receive the code - write it down somewhere.
80 | """), reply_markup=ListOfButtons(
81 | text=[_("Continue")],
82 | callback=["continue"]).inline_keyboard)
83 | await GoogleAuth.ONE.set()
84 |
85 |
86 | @dp.message_handler(commands=["cancel"], state=[GoogleAuth.TWO, GoogleAuth.ONE])
87 | async def reset(message: types.Message, state: FSMContext):
88 | await state.reset_state()
89 | chat_id = message.chat.id
90 |
91 | sql.update(table="users", google="", enabled=0, condition={"chat_id": chat_id})
92 | await message.reply(_("That is done"))
93 |
94 |
95 | @dp.message_handler(state=GoogleAuth.ONE)
96 | async def g_auth(message: types.Message, state: FSMContext):
97 | await message.reply(_("Please press on button to continue or /cancel"))
98 |
99 |
100 | @dp.callback_query_handler(state=GoogleAuth.ONE)
101 | async def g_auth(call: types.CallbackQuery, state: FSMContext):
102 | chat_id = call.message.chat.id
103 | try:
104 | await bot.edit_message_reply_markup(chat_id, message_id=call.message.message_id)
105 | except Exception as e:
106 | logging.error(f"{e}")
107 | if has_g_auth(chat_id):
108 | await bot.send_message(chat_id, _("You have already received the Google Authenticator code"))
109 | return
110 |
111 | code, link, qr_code = create_google_auth(chat_id)
112 | await bot.send_message(chat_id, _("""
113 | You will receive a recovery code and a link below.
114 | IT WILL BE AUTOMATICALLY DELETED AFTER YOU CONFIRM
115 | """))
116 | message_1 = (await bot.send_message(chat_id, code)).message_id
117 |
118 | message_2 = (await bot.send_photo(chat_id, qr_code,
119 | f"{link}")).message_id
120 | await bot.send_message(chat_id, _("Please enter the code from the Google Authenticator\n"
121 | "Pay attention that it updates every 30 sec."))
122 |
123 | await state.update_data(message_1=message_1, message_2=message_2)
124 | await GoogleAuth.next()
125 |
126 |
127 | @dp.message_handler(state=GoogleAuth.TWO)
128 | async def g_auth(message: types.Message, state: FSMContext):
129 | increase_message_counter()
130 | chat_id = message.chat.id
131 | try:
132 | ver = verify(chat_id, message.text)
133 | except binascii.Error:
134 | await bot.send_message(chat_id, _("Code is incorrect, try again or /cancel"))
135 | return
136 | if ver:
137 | async with state.proxy() as data:
138 | message_1 = data.get("message_1")
139 | message_2 = data.get("message_2")
140 | await bot.delete_message(chat_id, message_1)
141 | await bot.delete_message(chat_id, message_2)
142 | await bot.send_message(chat_id, _("Confirmation successful, you can proceed. /encode"))
143 | await state.finish()
144 | else:
145 | await bot.send_message(chat_id, _("Code is incorrect, try again or /cancel"))
146 |
--------------------------------------------------------------------------------
/bot/utils/sql.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | # vim:fileencoding=utf-8
4 | import pymysql
5 | from config import sql_config
6 |
7 |
8 | class Mysql(object):
9 | def __init__(self, params, debug=False):
10 | self.params = params
11 | self.connection = None
12 | self.debug = debug
13 | self.if_cursor_dict = False
14 |
15 | def connect(self):
16 | self.connection = pymysql.connect(**self.params)
17 | return self.connection
18 |
19 | def insert(self, table, returning=False, **kwargs):
20 | what = []
21 | if "what" in kwargs.keys():
22 | if isinstance(kwargs["what"], str):
23 | what = [kwargs["what"]]
24 | else:
25 | what = kwargs["what"]
26 | iterate = ", ".join(["%s" for _ in range(len(what))])
27 | if isinstance(kwargs["where"], list):
28 | where = ", ".join([
29 | item for item in kwargs["where"]
30 | ])
31 | else:
32 | where = kwargs["where"]
33 | else:
34 | where = ""
35 | iterate = ""
36 | for key, value in kwargs.items():
37 | if key not in ["returning", "table"]:
38 | where += "{}, ".format(key)
39 | iterate += "%s, "
40 | what.append(value)
41 | iterate = iterate[:-2]
42 | where = where[:-2]
43 | command = f"INSERT INTO `{table}`({where}) VALUES ({iterate})"
44 | return self.execute(command, what, returning=returning)
45 |
46 | def select(self, **kwargs):
47 | args = []
48 | if "what" not in kwargs.keys():
49 | what = "*"
50 | elif any([x in kwargs["what"] for x in ["SUM", "COUNT", "DISTINCT", "MAX"]]):
51 | what = kwargs["what"]
52 | else:
53 | if isinstance(kwargs["what"], str):
54 | kwargs["what"] = [kwargs["what"]]
55 | what = ", ".join([f"`{column_name}`" for column_name in kwargs["what"]])
56 | command = f"SELECT {what} FROM {kwargs['where']} "
57 | if "condition" in kwargs:
58 | command += " WHERE "
59 | for item, value in kwargs["condition"].items():
60 | if not any([x in str(value) for x in ["<", ">", "!", "IS"]]):
61 | if isinstance(value, str):
62 | command += f" `{item}` = %s AND"
63 | args.append(value)
64 | else:
65 | command += f" `{item}` = %s AND"
66 | args.append(value)
67 | else:
68 | command += f" `{item}` {value} AND"
69 | command = command[:-3] if command.endswith("AND") else command
70 | if "order" in kwargs:
71 | command += f" ORDER BY {kwargs['order']}"
72 |
73 | if "limit" in kwargs:
74 | command += " LIMIT {}".format(kwargs["limit"])
75 | return self.execute(command, args, select=True, kwargs=kwargs)
76 |
77 | def delete(self, table, where, what):
78 | if isinstance(where, str):
79 | where = [where]
80 | where = "AND ".join([f"`{wher}` = %s " for wher in where])
81 | return self.execute(command=f"DELETE FROM `{table}` WHERE {where}",
82 | args=what)
83 |
84 | def update(self, table, **kwargs):
85 | args = []
86 | command = "UPDATE `{0}` SET ".format(table)
87 | for items, value in kwargs.items():
88 | if items != "condition":
89 | if items == "raw":
90 | continue
91 | command += f" `{items}` = %s," if "raw" not in kwargs else f" `{items}` = {value},"
92 | args.append(value)
93 | command = command[:-1] if command.endswith(",") else command
94 | command += " WHERE "
95 | if "condition" in kwargs:
96 | for item, value in kwargs["condition"].items():
97 | command += f" `{item}` = %s AND" if "raw" not in kwargs else f" `{item}` = {value} AND"
98 | args.append(value)
99 | command = command[:-3] if command.endswith("AND") else command
100 | if "raw" in kwargs:
101 | args.clear()
102 | self.execute(command, args, kwargs=kwargs)
103 |
104 | def execute(self, command, args: tuple or list = (), kwargs: dict = {}, select=False, returning=False):
105 | self.connection = self.connect()
106 | c = None
107 | if self.if_cursor_dict:
108 | c = pymysql.cursors.DictCursor
109 | if self.debug:
110 | with self.connection.cursor(c) as cursor:
111 | print(command, args, kwargs)
112 | cursor.execute(command, (*args,))
113 | if returning:
114 | ids = cursor.lastrowid
115 | self.connection.commit()
116 | if select:
117 | values = cursor.fetchall()
118 | self.connection.close()
119 | if len(values) == 1:
120 | if isinstance(values[0], tuple) and len(values[0]) == 1:
121 | values = values[0][0]
122 | print(str(values).encode())
123 | return values
124 | elif returning:
125 | return ids
126 | else:
127 | cursor = self.connection.cursor(c)
128 | try:
129 | cursor.execute(command, (*args,))
130 | if returning:
131 | ids = cursor.lastrowid
132 | except self.connection.OperationalError as err:
133 | print(f"Operational error. restart {command}\n{kwargs}\n{err}")
134 | return
135 | # self.connection.close()
136 | # self.connect()
137 | # cursor = self.connection.cursor()
138 | # cursor.execute(command, (*args,))
139 | except self.connection.InterfaceError as err:
140 | print("InterfaceError (bad command), "
141 | "reconnecting, executing", err)
142 | return
143 |
144 | # self.connection.close()
145 | # self.connect()
146 | # cursor = self.connection.cursor()
147 | # cursor.execute(command, (*args,))
148 | except self.connection.ProgrammingError as err:
149 | print(f"Programming error (bad command), {err} \n{[command, kwargs, args]} ")
150 | return
151 | except self.connection.IntegrityError as err:
152 | print("IntegrityError, dublicate primary key? ", err)
153 | return
154 |
155 | except Exception as err:
156 | print(f"Other error. {command}\n {kwargs}, \n{err}")
157 | return
158 |
159 | finally:
160 | print(f"CONFIG {self.params}")
161 |
162 | if select:
163 | values = cursor.fetchall()
164 | self.connection.close()
165 | if len(values) == 1:
166 | if isinstance(values[0], tuple) and len(values[0]) == 1:
167 | values = values[0][0]
168 |
169 | return values
170 | else:
171 | self.connection.commit()
172 | self.connection.close()
173 | if returning:
174 | return ids
175 |
176 |
177 | sql = Mysql(sql_config)
178 |
--------------------------------------------------------------------------------
/bot/handlers/encoding.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 |
3 | from aiogram import types
4 | from aiogram.dispatcher import FSMContext
5 | from aiogram.utils.exceptions import BadRequest
6 |
7 | from bot.load_all import bot, dp, _
8 | from bot.aiogram_help.keyboard_maker import ListOfButtons
9 | from bot.aiogram_help.states import Encode
10 | from bot.utils.encode import encode
11 | from bot.utils.google_auth import enabled_g_auth, get_google_auth
12 | from bot.utils.some_functions import allowed_chars
13 | from bot.utils.some_functions import increase_message_counter
14 |
15 |
16 | @dp.message_handler(commands=["encode", "e"])
17 | async def encode_start(message: types.Message, state: FSMContext):
18 | increase_message_counter()
19 | chat_id = message.chat.id
20 | if not enabled_g_auth(chat_id):
21 | await bot.send_message(chat_id, _("""
22 | Please enter your master password.
23 | You can make everything faster with Google Authenticator!
24 | Press /g_auth_info
25 |
26 | """))
27 | await Encode.MASTER_PASSWORD.set()
28 | else:
29 | await state.update_data(master_pass=get_google_auth(chat_id))
30 | await Encode.PASSWORD.set()
31 | await bot.send_message(chat_id, _("""Enter phrase you want to encrypt.
32 | It should be under 400 characters, for best results there should be only characters from this list:
33 | {allowed_chars}
34 | THE BOT DELETES YOUR MESSAGES WITH PASSWORDS AFTER 10 SECONDS
35 | """).format(allowed_chars=allowed_chars))
36 |
37 |
38 | @dp.callback_query_handler(text="encrypt_saved")
39 | async def encode_saved(call: types.CallbackQuery, state: FSMContext):
40 | chat_id = call.from_user.id
41 | password_message = call.message.reply_to_message
42 | password = password_message.text
43 | await call.message.delete()
44 | async with state.proxy() as data:
45 | data["encrypt_from_saved"] = True
46 | data["to_encrypt"] = password
47 |
48 | await password_message.delete()
49 |
50 | if not enabled_g_auth(chat_id):
51 | await bot.send_message(chat_id, _("""
52 | Please enter your master password.
53 | You can make everything faster with Google Authenticator!
54 | Press /g_auth_info
55 |
56 | """))
57 | await Encode.MASTER_PASSWORD.set()
58 | else:
59 |
60 | master_pass = get_google_auth(chat_id)
61 |
62 | if len(password) > 400:
63 | await bot.send_message(chat_id, _("Error has occurred... Too long phrase. Try to enter a phrase \
64 | under 400 characters."))
65 | return
66 | elif not master_pass:
67 | await bot.send_message(chat_id, _("Master Password not found."))
68 | await state.finish()
69 | return
70 |
71 | text, code = encode(password.replace("\n", "\\n"), master_pass)
72 | hint = "Google Authenticator"
73 | await bot.send_message(chat_id, _("""----------------------------
74 | ENCRYPTION STARTS HERE
75 | ----------------------------
76 | {passw}
77 | ----------------------------
78 | ENCRYPTION ENDS HERE
79 | ----------------------------
80 | CODE
81 | {code}
82 | ----------------------------
83 |
84 |
85 | Hint: {hint}
86 | Save this message wherever you want and forward it to the bot should you need to decode it.
87 | """).format(
88 | passw=text, code=code,
89 | hint=f"{hint}"
90 | ))
91 | await state.finish()
92 | increase_message_counter(password=True)
93 |
94 | await asyncio.sleep(10)
95 |
96 |
97 | @dp.message_handler(state=Encode.MASTER_PASSWORD)
98 | async def encoded(message: types.Message, state: FSMContext):
99 | increase_message_counter()
100 | chat_id = message.chat.id
101 | if "/g_auth_info" == message.text:
102 | text = _(
103 | "To encrypt your phrase/file you need to enter a master password each time you want to encrypt or decrypt, or"
104 | " you can enable Google Authenticator and enter one-time codes from your phone only to decrypt"
105 | " your passwords. \n"
106 | "(Master password will be kept in database then) \n\n"
107 | "Please make your choice (you can change it later with command /reset_google_auth\n"
108 | )
109 | await bot.send_message(chat_id, text, reply_markup=ListOfButtons(
110 | text=[_("Setup")],
111 | callback=["g_auth_setup"]).inline_keyboard)
112 | await state.finish()
113 | return
114 | async with state.proxy() as data:
115 | data["master_pass"] = message.text
116 |
117 | password = data.get("to_encrypt")
118 | master_pass = data.get("master_pass")
119 |
120 | if not data.get("encrypt_from_saved"):
121 | await Encode.PASSWORD.set()
122 | await bot.send_message(chat_id, _("""Enter phrase you want to encrypt.
123 | It should be under 400 characters, for best results there should be only characters from this list:
124 | {allowed_chars}
125 | THE BOT DELETES YOUR MESSAGES WITH PASSWORDS AFTER 10 SECONDS
126 | """).format(allowed_chars=allowed_chars))
127 | else:
128 | if not password:
129 | await message.reply(_("Password not found."))
130 | await state.finish()
131 | return
132 | if len(password) > 400:
133 | await bot.send_message(chat_id, _("Error has occurred... Too long phrase. Try to enter a phrase under 400 \
134 | characters."))
135 | await state.finish()
136 | return
137 | elif not master_pass:
138 | await message.reply(_("Master Password not found."))
139 | await state.finish()
140 | return
141 |
142 | text, code = encode(password.replace("\n", "\\n"), master_pass)
143 | if master_pass == get_google_auth(chat_id):
144 | hint = "Google Authenticator"
145 | else:
146 | hint = master_pass[:2] + "***********"
147 | await bot.send_message(chat_id, _("""----------------------------
148 | ENCRYPTION STARTS HERE
149 | ----------------------------
150 | {passw}
151 | ----------------------------
152 | ENCRYPTION ENDS HERE
153 | ----------------------------
154 | CODE
155 | {code}
156 | ----------------------------
157 |
158 |
159 | Hint: {hint}
160 | Save this message wherever you want and forward it to the bot should you need to decode it.
161 | """).format(
162 | passw=text, code=code,
163 | hint=f"{hint}"
164 | ))
165 | await state.finish()
166 | increase_message_counter(password=True)
167 |
168 | await asyncio.sleep(10)
169 | await message.delete()
170 |
171 |
172 | @dp.message_handler(state=Encode.PASSWORD, content_types=types.ContentType.TEXT)
173 | async def encoded(message: types.Message, state: FSMContext):
174 | increase_message_counter(password=True)
175 | chat_id = message.chat.id
176 | master_pass = (await state.get_data()).get("master_pass")
177 | if len(message.text) > 400:
178 | await bot.send_message(chat_id, _("Error has occurred... Too long phrase. Try to enter a phrase under 400 \
179 | characters."))
180 | return
181 | elif not master_pass:
182 | await message.reply(_("Master Password not found."))
183 | await state.finish()
184 | await asyncio.sleep(10)
185 | await message.delete()
186 | return
187 | text, code = encode(message.text.replace("\n", "\\n"), master_pass)
188 | if master_pass == get_google_auth(chat_id):
189 | hint = "Google Authenticator"
190 | else:
191 | hint = master_pass[:2] + "***********"
192 | await bot.send_message(chat_id, _("""----------------------------
193 | ENCRYPTION STARTS HERE
194 | ----------------------------
195 | {passw}
196 | ----------------------------
197 | ENCRYPTION ENDS HERE
198 | ----------------------------
199 | CODE
200 | {code}
201 | ----------------------------
202 |
203 |
204 | Hint: {hint}
205 | Save this message wherever you want and forward it to the bot should you need to decode it.
206 | """).format(
207 | passw=text, code=code,
208 | hint=f"{hint}"
209 | ))
210 | await state.finish()
211 | await asyncio.sleep(10)
212 | await message.delete()
213 |
214 |
215 | @dp.message_handler(state=Encode.PASSWORD, content_types=types.ContentType.DOCUMENT)
216 | async def encoded(message: types.Message, state: FSMContext):
217 | increase_message_counter(password=True)
218 | chat_id = message.chat.id
219 | master_pass = (await state.get_data()).get("master_pass")
220 | file_id = message.document.file_id
221 | try:
222 | await bot.download_file_by_id(file_id, "to_encode.txt")
223 | except BadRequest:
224 | return await message.reply(_("INVALID FILE"))
225 | with open("to_encode.txt", "r") as file:
226 | try:
227 | text = file.read().replace("\n", "\\n")
228 | except UnicodeDecodeError:
229 | await bot.send_message(chat_id, _("INVALID FILE"))
230 | await state.finish()
231 | return
232 |
233 | text, code = encode(text, master_pass)
234 | with open("encoded.txt", "a") as file:
235 | file.write(_("""
236 | ----------------------------
237 | ENCRYPTION STARTS HERE
238 | ----------------------------
239 | {passw}
240 | ----------------------------
241 | ENCRYPTION ENDS HERE
242 | ----------------------------
243 | CODE
244 | {code}
245 | ----------------------------
246 | Hint: {hint}
247 | """).format(
248 | passw=text, code=code,
249 | hint=f"{master_pass[:2]}***********"))
250 | await bot.send_document(chat_id, open("encoded.txt", "rb"))
251 |
252 | with open("encoded.txt", "w") as file:
253 | file.write(" ")
254 |
255 | with open("to_encode.txt", "w") as file:
256 | file.write(" ")
257 | await state.finish()
258 |
259 | await asyncio.sleep(10)
260 | await message.delete()
261 |
--------------------------------------------------------------------------------
/locales/pcypher.pot:
--------------------------------------------------------------------------------
1 | # Translations template for PROJECT.
2 | # Copyright (C) 2019 ORGANIZATION
3 | # This file is distributed under the same license as the PROJECT project.
4 | # FIRST AUTHOR {allowed_chars} \n"
42 | " THE BOT DELETES YOUR MESSAGES WITH PASSWORDS AFTER 10 SECONDS\n"
43 | msgstr ""
44 |
45 | #: bot/handlers/buttons.py:40
46 | msgid "https://telegra.ph/Passwords-Decryption-Process-06-02"
47 | msgstr ""
48 |
49 | #: bot/handlers/buttons.py:55
50 | msgid ""
51 | "\n"
52 | "Hello, {}\n"
53 | "Let's choose your language\n"
54 | msgstr ""
55 |
56 | #: bot/handlers/buttons.py:69
57 | msgid "https://telegra.ph/Passcypher-Google-Authenticator-06-02"
58 | msgstr ""
59 |
60 | #: bot/handlers/buttons.py:73 bot/handlers/buttons.py:80
61 | #: bot/handlers/setup_gauth.py:33
62 | msgid "Here you can enable and disable your Google Authenticator settings"
63 | msgstr ""
64 |
65 | #: bot/handlers/buttons.py:75 bot/handlers/setup_gauth.py:37
66 | msgid "Turn off"
67 | msgstr ""
68 |
69 | #: bot/handlers/buttons.py:82 bot/handlers/setup_gauth.py:43
70 | msgid "Turn on"
71 | msgstr ""
72 |
73 | #: bot/handlers/buttons.py:85 bot/handlers/setup_gauth.py:46
74 | msgid "Google Authenticator is not set for you. Press /g_auth_info"
75 | msgstr ""
76 |
77 | #: bot/handlers/decoding.py:27 bot/handlers/decoding.py:89
78 | msgid "Error. Wrong file"
79 | msgstr ""
80 |
81 | #: bot/handlers/decoding.py:41 bot/handlers/decoding.py:65
82 | #: bot/handlers/decoding.py:103
83 | msgid "Enter the code from the app"
84 | msgstr ""
85 |
86 | #: bot/handlers/decoding.py:54
87 | msgid "Error"
88 | msgstr ""
89 |
90 | #: bot/handlers/decoding.py:77 bot/handlers/decoding.py:82
91 | #: bot/handlers/encoding.py:224 bot/handlers/encoding.py:229
92 | msgid "INVALID FILE"
93 | msgstr ""
94 |
95 | #: bot/handlers/decoding.py:127
96 | msgid ""
97 | "An error has occurred, you lost the Google authenticator settings\n"
98 | "Please re-configure it once again /g_auth_info"
99 | msgstr ""
100 |
101 | #: bot/handlers/decoding.py:136 bot/handlers/decoding.py:139
102 | #: bot/handlers/setup_gauth.py:134 bot/handlers/setup_gauth.py:145
103 | msgid "Code is incorrect, try again or /cancel"
104 | msgstr ""
105 |
106 | #: bot/handlers/decoding.py:152
107 | msgid ""
108 | "\n"
109 | "Your decoded password is inside citation marks '{password}'"
110 | msgstr ""
111 |
112 | #: bot/handlers/encoding.py:63 bot/handlers/encoding.py:133
113 | #: bot/handlers/encoding.py:178
114 | msgid ""
115 | "Error has occurred... Too long phrase. Try to enter a phrase under 400 "
116 | "characters."
117 | msgstr ""
118 |
119 | #: bot/handlers/encoding.py:67 bot/handlers/encoding.py:138
120 | #: bot/handlers/encoding.py:182
121 | msgid "Master Password not found."
122 | msgstr ""
123 |
124 | #: bot/handlers/encoding.py:73 bot/handlers/encoding.py:147
125 | #: bot/handlers/encoding.py:192
126 | msgid ""
127 | "----------------------------\n"
128 | "ENCRYPTION STARTS HERE\n"
129 | "----------------------------\n"
130 | "{passw}\n"
131 | "----------------------------\n"
132 | "ENCRYPTION ENDS HERE\n"
133 | "----------------------------\n"
134 | "CODE\n"
135 | "{code}\n"
136 | "----------------------------\n"
137 | "\n"
138 | "\n"
139 | "Hint: {hint}\n"
140 | "Save this message wherever you want and forward it to the bot should you "
141 | "need to decode it.\n"
142 | msgstr ""
143 |
144 | #: bot/handlers/encoding.py:102 bot/handlers/setup_gauth.py:17
145 | msgid ""
146 | "To encrypt your phrase/file you need to enter a master password each time"
147 | " you want to encrypt or decrypt, or you can enable Google "
148 | "Authenticator and enter one-time codes from your phone only to "
149 | "decrypt your passwords. \n"
150 | "(Master password will be kept in database then) \n"
151 | "\n"
152 | "Please make your choice (you can change it later with command "
153 | "/reset_google_auth\n"
154 | msgstr ""
155 |
156 | #: bot/handlers/encoding.py:110 bot/handlers/setup_gauth.py:24
157 | msgid "Setup"
158 | msgstr ""
159 |
160 | #: bot/handlers/encoding.py:129
161 | msgid "Password not found."
162 | msgstr ""
163 |
164 | #: bot/handlers/encoding.py:235
165 | msgid ""
166 | "\n"
167 | "----------------------------\n"
168 | "ENCRYPTION STARTS HERE\n"
169 | "----------------------------\n"
170 | "{passw}\n"
171 | "----------------------------\n"
172 | "ENCRYPTION ENDS HERE\n"
173 | "----------------------------\n"
174 | "CODE\n"
175 | "{code}\n"
176 | "----------------------------\n"
177 | "Hint: {hint}\n"
178 | msgstr ""
179 |
180 | #: bot/handlers/main_handlers.py:18 bot/handlers/main_handlers.py:48
181 | #: bot/handlers/main_handlers.py:102 bot/handlers/main_handlers.py:108
182 | msgid "🔒 Encode"
183 | msgstr ""
184 |
185 | #: bot/handlers/main_handlers.py:19 bot/handlers/main_handlers.py:49
186 | msgid "🔑 Decode"
187 | msgstr ""
188 |
189 | #: bot/handlers/main_handlers.py:20 bot/handlers/main_handlers.py:50
190 | msgid "ℹ️How to use"
191 | msgstr ""
192 |
193 | #: bot/handlers/main_handlers.py:21 bot/handlers/main_handlers.py:51
194 | msgid "🇬🇧 Set language"
195 | msgstr ""
196 |
197 | #: bot/handlers/main_handlers.py:22 bot/handlers/main_handlers.py:52
198 | msgid "🔐 Two step verification"
199 | msgstr ""
200 |
201 | #: bot/handlers/main_handlers.py:23 bot/handlers/main_handlers.py:53
202 | msgid "📝 Write a review"
203 | msgstr ""
204 |
205 | #: bot/handlers/main_handlers.py:28
206 | msgid ""
207 | "\n"
208 | "Hello, {}\n"
209 | "This bot is designed to encrypt your passwords so you can store them "
210 | "publicly, for example in your Telegram saved messages.\n"
211 | "\n"
212 | "You can choose your language using command /set_language\n"
213 | msgstr ""
214 |
215 | #: bot/handlers/main_handlers.py:57
216 | msgid ""
217 | "Language has changed to 🇬🇧EN\n"
218 | "\n"
219 | "{users} users are using this bot. \n"
220 | "\n"
221 | "{passwords} passwords encrypted.\n"
222 | "{messages} messages received.\n"
223 | "\n"
224 | "Start using this bot: /info"
225 | msgstr ""
226 |
227 | #: bot/handlers/main_handlers.py:71
228 | msgid ""
229 | "\n"
230 | "{users} users are using this bot. \n"
231 | "\n"
232 | "{passwords} passwords encrypted.\n"
233 | "{messages} messages received.\n"
234 | " "
235 | msgstr ""
236 |
237 | #: bot/handlers/main_handlers.py:86
238 | msgid ""
239 | "\n"
240 | "Hello, {}\n"
241 | "Firstly, let's choose your language\n"
242 | msgstr ""
243 |
244 | #: bot/handlers/main_handlers.py:104
245 | msgid ""
246 | "\n"
247 | "Looks like the input is invalid...\n"
248 | "To decode your password - forward the message with encoded password you "
249 | "received from bot.\n"
250 | "ᅠ\n"
251 | "Perhaps you wanted to encrypt this message? Click "
252 | msgstr ""
253 |
254 | #: bot/handlers/main_handlers.py:109
255 | msgid ""
256 | "\n"
257 | "\n"
258 | "Or setup the language again /set_language"
259 | msgstr ""
260 |
261 | #: bot/handlers/main_handlers.py:118 bot/handlers/main_handlers.py:123
262 | msgid "Seems like you have an unfinished business..."
263 | msgstr ""
264 |
265 | #: bot/handlers/reviews.py:17
266 | msgid ""
267 | "Please, it is important for me to receive a response and advice from you."
268 | "\n"
269 | "How would you change the bot? Any comments are appreciated. \n"
270 | "\n"
271 | "Your comment will be posted anonymously in our channel @pcypher\n"
272 | "Or you can just rate the bot using this link: https://t.me/pcypher/16\n"
273 | msgstr ""
274 |
275 | #: bot/handlers/reviews.py:24
276 | msgid "Give an advice to the bot"
277 | msgstr ""
278 |
279 | #: bot/handlers/reviews.py:34 bot/handlers/reviews.py:57
280 | msgid ""
281 | "\n"
282 | "Your advice: \n"
283 | "\n"
284 | "{advice}\n"
285 | "\n"
286 | "Write your advice in the next message.\n"
287 | msgstr ""
288 |
289 | #: bot/handlers/reviews.py:42 bot/handlers/reviews.py:67
290 | msgid "Cancel"
291 | msgstr ""
292 |
293 | #: bot/handlers/reviews.py:66
294 | msgid "Publish"
295 | msgstr ""
296 |
297 | #: bot/handlers/reviews.py:87
298 | msgid "Cancelled"
299 | msgstr ""
300 |
301 | #: bot/handlers/reviews.py:92
302 | msgid ""
303 | "\n"
304 | "#Reviews Post:\n"
305 | "\n"
306 | "{}\n"
307 | msgstr ""
308 |
309 | #: bot/handlers/setup_gauth.py:55 bot/handlers/setup_gauth.py:92
310 | msgid "That is done"
311 | msgstr ""
312 |
313 | #: bot/handlers/setup_gauth.py:71 bot/handlers/setup_gauth.py:108
314 | msgid "You have already received the Google Authenticator code"
315 | msgstr ""
316 |
317 | #: bot/handlers/setup_gauth.py:74
318 | msgid ""
319 | "\n"
320 | "Please ensure you have the app installed.\n"
321 | "IOS\n"
323 | "Android"
325 | "\n"
326 | "\n"
327 | "Press continue when you done. After you receive the code - write it down "
328 | "somewhere.\n"
329 | msgstr ""
330 |
331 | #: bot/handlers/setup_gauth.py:81
332 | msgid "Continue"
333 | msgstr ""
334 |
335 | #: bot/handlers/setup_gauth.py:97
336 | msgid "Please press on button to continue or /cancel"
337 | msgstr ""
338 |
339 | #: bot/handlers/setup_gauth.py:112
340 | msgid ""
341 | "\n"
342 | "You will receive a recovery code and a link below.\n"
343 | "IT WILL BE AUTOMATICALLY DELETED AFTER YOU CONFIRM\n"
344 | msgstr ""
345 |
346 | #: bot/handlers/setup_gauth.py:120
347 | msgid ""
348 | "Please enter the code from the Google Authenticator\n"
349 | "Pay attention that it updates every 30 sec."
350 | msgstr ""
351 |
352 | #: bot/handlers/setup_gauth.py:142
353 | msgid "Confirmation successful, you can proceed. /encode"
354 | msgstr ""
355 |
356 |
--------------------------------------------------------------------------------
/locales/en/LC_MESSAGES/pcypher.po:
--------------------------------------------------------------------------------
1 | # English translations for PROJECT.
2 | # Copyright (C) 2019 ORGANIZATION
3 | # This file is distributed under the same license as the PROJECT project.
4 | # FIRST AUTHOR {allowed_chars} \n"
43 | " THE BOT DELETES YOUR MESSAGES WITH PASSWORDS AFTER 10 SECONDS\n"
44 | msgstr ""
45 |
46 | #: bot/handlers/buttons.py:40
47 | msgid "https://telegra.ph/Passwords-Decryption-Process-06-02"
48 | msgstr ""
49 |
50 | #: bot/handlers/buttons.py:55
51 | msgid ""
52 | "\n"
53 | "Hello, {}\n"
54 | "Let's choose your language\n"
55 | msgstr ""
56 |
57 | #: bot/handlers/buttons.py:69
58 | msgid "https://telegra.ph/Passcypher-Google-Authenticator-06-02"
59 | msgstr ""
60 |
61 | #: bot/handlers/buttons.py:73 bot/handlers/buttons.py:80
62 | #: bot/handlers/setup_gauth.py:33
63 | msgid "Here you can enable and disable your Google Authenticator settings"
64 | msgstr ""
65 |
66 | #: bot/handlers/buttons.py:75 bot/handlers/setup_gauth.py:37
67 | msgid "Turn off"
68 | msgstr ""
69 |
70 | #: bot/handlers/buttons.py:82 bot/handlers/setup_gauth.py:43
71 | msgid "Turn on"
72 | msgstr ""
73 |
74 | #: bot/handlers/buttons.py:85 bot/handlers/setup_gauth.py:46
75 | msgid "Google Authenticator is not set for you. Press /g_auth_info"
76 | msgstr ""
77 |
78 | #: bot/handlers/decoding.py:27 bot/handlers/decoding.py:89
79 | msgid "Error. Wrong file"
80 | msgstr ""
81 |
82 | #: bot/handlers/decoding.py:41 bot/handlers/decoding.py:65
83 | #: bot/handlers/decoding.py:103
84 | msgid "Enter the code from the app"
85 | msgstr ""
86 |
87 | #: bot/handlers/decoding.py:54
88 | msgid "Error"
89 | msgstr ""
90 |
91 | #: bot/handlers/decoding.py:77 bot/handlers/decoding.py:82
92 | #: bot/handlers/encoding.py:224 bot/handlers/encoding.py:229
93 | msgid "INVALID FILE"
94 | msgstr ""
95 |
96 | #: bot/handlers/decoding.py:127
97 | msgid ""
98 | "An error has occurred, you lost the Google authenticator settings\n"
99 | "Please re-configure it once again /g_auth_info"
100 | msgstr ""
101 |
102 | #: bot/handlers/decoding.py:136 bot/handlers/decoding.py:139
103 | #: bot/handlers/setup_gauth.py:134 bot/handlers/setup_gauth.py:145
104 | msgid "Code is incorrect, try again or /cancel"
105 | msgstr ""
106 |
107 | #: bot/handlers/decoding.py:152
108 | msgid ""
109 | "\n"
110 | "Your decoded password is inside citation marks '{password}'"
111 | msgstr ""
112 |
113 | #: bot/handlers/encoding.py:63 bot/handlers/encoding.py:133
114 | #: bot/handlers/encoding.py:178
115 | msgid ""
116 | "Error has occurred... Too long phrase. Try to enter a phrase under 400 "
117 | "characters."
118 | msgstr ""
119 |
120 | #: bot/handlers/encoding.py:67 bot/handlers/encoding.py:138
121 | #: bot/handlers/encoding.py:182
122 | msgid "Master Password not found."
123 | msgstr ""
124 |
125 | #: bot/handlers/encoding.py:73 bot/handlers/encoding.py:147
126 | #: bot/handlers/encoding.py:192
127 | msgid ""
128 | "----------------------------\n"
129 | "ENCRYPTION STARTS HERE\n"
130 | "----------------------------\n"
131 | "{passw}\n"
132 | "----------------------------\n"
133 | "ENCRYPTION ENDS HERE\n"
134 | "----------------------------\n"
135 | "CODE\n"
136 | "{code}\n"
137 | "----------------------------\n"
138 | "\n"
139 | "\n"
140 | "Hint: {hint}\n"
141 | "Save this message wherever you want and forward it to the bot should you "
142 | "need to decode it.\n"
143 | msgstr ""
144 |
145 | #: bot/handlers/encoding.py:102 bot/handlers/setup_gauth.py:17
146 | msgid ""
147 | "To encrypt your phrase/file you need to enter a master password each time"
148 | " you want to encrypt or decrypt, or you can enable Google "
149 | "Authenticator and enter one-time codes from your phone only to "
150 | "decrypt your passwords. \n"
151 | "(Master password will be kept in database then) \n"
152 | "\n"
153 | "Please make your choice (you can change it later with command "
154 | "/reset_google_auth\n"
155 | msgstr ""
156 |
157 | #: bot/handlers/encoding.py:110 bot/handlers/setup_gauth.py:24
158 | msgid "Setup"
159 | msgstr ""
160 |
161 | #: bot/handlers/encoding.py:129
162 | msgid "Password not found."
163 | msgstr ""
164 |
165 | #: bot/handlers/encoding.py:235
166 | msgid ""
167 | "\n"
168 | "----------------------------\n"
169 | "ENCRYPTION STARTS HERE\n"
170 | "----------------------------\n"
171 | "{passw}\n"
172 | "----------------------------\n"
173 | "ENCRYPTION ENDS HERE\n"
174 | "----------------------------\n"
175 | "CODE\n"
176 | "{code}\n"
177 | "----------------------------\n"
178 | "Hint: {hint}\n"
179 | msgstr ""
180 |
181 | #: bot/handlers/main_handlers.py:18 bot/handlers/main_handlers.py:48
182 | #: bot/handlers/main_handlers.py:102 bot/handlers/main_handlers.py:108
183 | msgid "🔒 Encode"
184 | msgstr ""
185 |
186 | #: bot/handlers/main_handlers.py:19 bot/handlers/main_handlers.py:49
187 | msgid "🔑 Decode"
188 | msgstr ""
189 |
190 | #: bot/handlers/main_handlers.py:20 bot/handlers/main_handlers.py:50
191 | msgid "ℹ️How to use"
192 | msgstr ""
193 |
194 | #: bot/handlers/main_handlers.py:21 bot/handlers/main_handlers.py:51
195 | msgid "🇬🇧 Set language"
196 | msgstr ""
197 |
198 | #: bot/handlers/main_handlers.py:22 bot/handlers/main_handlers.py:52
199 | msgid "🔐 Two step verification"
200 | msgstr ""
201 |
202 | #: bot/handlers/main_handlers.py:23 bot/handlers/main_handlers.py:53
203 | msgid "📝 Write a review"
204 | msgstr ""
205 |
206 | #: bot/handlers/main_handlers.py:28
207 | msgid ""
208 | "\n"
209 | "Hello, {}\n"
210 | "This bot is designed to encrypt your passwords so you can store them "
211 | "publicly, for example in your Telegram saved messages.\n"
212 | "\n"
213 | "You can choose your language using command /set_language\n"
214 | msgstr ""
215 |
216 | #: bot/handlers/main_handlers.py:57
217 | msgid ""
218 | "Language has changed to 🇬🇧EN\n"
219 | "\n"
220 | "{users} users are using this bot. \n"
221 | "\n"
222 | "{passwords} passwords encrypted.\n"
223 | "{messages} messages received.\n"
224 | "\n"
225 | "Start using this bot: /info"
226 | msgstr ""
227 |
228 | #: bot/handlers/main_handlers.py:71
229 | msgid ""
230 | "\n"
231 | "{users} users are using this bot. \n"
232 | "\n"
233 | "{passwords} passwords encrypted.\n"
234 | "{messages} messages received.\n"
235 | " "
236 | msgstr ""
237 |
238 | #: bot/handlers/main_handlers.py:86
239 | msgid ""
240 | "\n"
241 | "Hello, {}\n"
242 | "Firstly, let's choose your language\n"
243 | msgstr ""
244 |
245 | #: bot/handlers/main_handlers.py:104
246 | msgid ""
247 | "\n"
248 | "Looks like the input is invalid...\n"
249 | "To decode your password - forward the message with encoded password you "
250 | "received from bot.\n"
251 | "ᅠ\n"
252 | "Perhaps you wanted to encrypt this message? Click "
253 | msgstr ""
254 |
255 | #: bot/handlers/main_handlers.py:109
256 | msgid ""
257 | "\n"
258 | "\n"
259 | "Or setup the language again /set_language"
260 | msgstr ""
261 |
262 | #: bot/handlers/main_handlers.py:118 bot/handlers/main_handlers.py:123
263 | msgid "Seems like you have an unfinished business..."
264 | msgstr ""
265 |
266 | #: bot/handlers/reviews.py:17
267 | msgid ""
268 | "Please, it is important for me to receive a response and advice from you."
269 | "\n"
270 | "How would you change the bot? Any comments are appreciated. \n"
271 | "\n"
272 | "Your comment will be posted anonymously in our channel @pcypher\n"
273 | "Or you can just rate the bot using this link: https://t.me/pcypher/16\n"
274 | msgstr ""
275 |
276 | #: bot/handlers/reviews.py:24
277 | msgid "Give an advice to the bot"
278 | msgstr ""
279 |
280 | #: bot/handlers/reviews.py:34 bot/handlers/reviews.py:57
281 | msgid ""
282 | "\n"
283 | "Your advice: \n"
284 | "\n"
285 | "{advice}\n"
286 | "\n"
287 | "Write your advice in the next message.\n"
288 | msgstr ""
289 |
290 | #: bot/handlers/reviews.py:42 bot/handlers/reviews.py:67
291 | msgid "Cancel"
292 | msgstr ""
293 |
294 | #: bot/handlers/reviews.py:66
295 | msgid "Publish"
296 | msgstr ""
297 |
298 | #: bot/handlers/reviews.py:87
299 | msgid "Cancelled"
300 | msgstr ""
301 |
302 | #: bot/handlers/reviews.py:92
303 | msgid ""
304 | "\n"
305 | "#Reviews Post:\n"
306 | "\n"
307 | "{}\n"
308 | msgstr ""
309 |
310 | #: bot/handlers/setup_gauth.py:55 bot/handlers/setup_gauth.py:92
311 | msgid "That is done"
312 | msgstr ""
313 |
314 | #: bot/handlers/setup_gauth.py:71 bot/handlers/setup_gauth.py:108
315 | msgid "You have already received the Google Authenticator code"
316 | msgstr ""
317 |
318 | #: bot/handlers/setup_gauth.py:74
319 | msgid ""
320 | "\n"
321 | "Please ensure you have the app installed.\n"
322 | "IOS\n"
324 | "Android"
326 | "\n"
327 | "\n"
328 | "Press continue when you done. After you receive the code - write it down "
329 | "somewhere.\n"
330 | msgstr ""
331 |
332 | #: bot/handlers/setup_gauth.py:81
333 | msgid "Continue"
334 | msgstr ""
335 |
336 | #: bot/handlers/setup_gauth.py:97
337 | msgid "Please press on button to continue or /cancel"
338 | msgstr ""
339 |
340 | #: bot/handlers/setup_gauth.py:112
341 | msgid ""
342 | "\n"
343 | "You will receive a recovery code and a link below.\n"
344 | "IT WILL BE AUTOMATICALLY DELETED AFTER YOU CONFIRM\n"
345 | msgstr ""
346 |
347 | #: bot/handlers/setup_gauth.py:120
348 | msgid ""
349 | "Please enter the code from the Google Authenticator\n"
350 | "Pay attention that it updates every 30 sec."
351 | msgstr ""
352 |
353 | #: bot/handlers/setup_gauth.py:142
354 | msgid "Confirmation successful, you can proceed. /encode"
355 | msgstr ""
356 |
357 | #~ msgid ""
358 | #~ "\n"
359 | #~ "Hello, {}\n"
360 | #~ "This bot is designed to encrypt "
361 | #~ "your passwords so you can store "
362 | #~ "them publicly, for example in your "
363 | #~ "Telegram saved messages.\n"
364 | #~ "\n"
365 | #~ "Firstly, let's choose your language\n"
366 | #~ msgstr ""
367 |
368 | #~ msgid ""
369 | #~ "To encrypt your phrase/file you need "
370 | #~ "to enter a master password each "
371 | #~ "time you want to encrypt or "
372 | #~ "decrypt, or you can enable Google "
373 | #~ "Authenticator and enter one-time "
374 | #~ "codes from your phone only to "
375 | #~ "decrypt your passwords. \\n(Master "
376 | #~ "password will be kept in database "
377 | #~ "then) \n"
378 | #~ "\n"
379 | #~ "Please make your choice (you can "
380 | #~ "change it later with command "
381 | #~ "/reset_google_auth\n"
382 | #~ msgstr ""
383 |
384 | #~ msgid ""
385 | #~ "To encrypt your phrase/file you need "
386 | #~ "to enter a master password each "
387 | #~ "time you want to encrypt or "
388 | #~ "decrypt, or you can enable Google "
389 | #~ "Authenticator and enter one-time "
390 | #~ "codes from your phone only to "
391 | #~ "decrypt your passwords. (Master password"
392 | #~ " will be kept in database then) \n"
393 | #~ ""
394 | #~ "\n"
395 | #~ "Please make your choice (you can "
396 | #~ "change it later with command "
397 | #~ "/reset_google_auth\n"
398 | #~ msgstr ""
399 |
400 | #~ msgid ""
401 | #~ "----------------------------\n"
402 | #~ "ENCRYPTION STARTS HERE\n"
403 | #~ "----------------------------\n"
404 | #~ "{passw}\n"
405 | #~ "----------------------------\n"
406 | #~ "ENCRYPTION ENDS HERE\n"
407 | #~ "----------------------------\n"
408 | #~ "CODE\n"
409 | #~ "{code}\n"
410 | #~ "----------------------------\n"
411 | #~ "\n"
412 | #~ "\n"
413 | #~ "Hint: {hint}\n"
414 | #~ "Save this message wherever you want "
415 | #~ "and forward it to the bot should"
416 | #~ " you need to decode it.\n"
417 | #~ " "
418 | #~ msgstr ""
419 |
420 | #~ msgid ""
421 | #~ "\n"
422 | #~ "Please enter your master password.\n"
423 | #~ "You can make everything faster with Google Authenticator! \n"
424 | #~ "Press /g_auth_info\n"
425 | #~ msgstr ""
426 |
427 | #~ msgid ""
428 | #~ "\n"
429 | #~ "Looks like the input is invalid...\n"
430 | #~ "To decode your password - forward "
431 | #~ "the message with encoded password you"
432 | #~ " received from bot.\n"
433 | #~ "ᅠ\n"
434 | #~ "Perhaps you wanted to encrypt this message? Click Encrypt ."
435 | #~ msgstr ""
436 |
437 |
--------------------------------------------------------------------------------
/locales/ru/LC_MESSAGES/pcypher.po:
--------------------------------------------------------------------------------
1 | # Russian translations for PROJECT.
2 | # Copyright (C) 2019 ORGANIZATION
3 | # This file is distributed under the same license as the PROJECT project.
4 | # FIRST AUTHOR {allowed_chars} \n"
51 | " THE BOT DELETES YOUR MESSAGES WITH PASSWORDS AFTER 10 SECONDS\n"
52 | msgstr ""
53 | "Введите пароль, который хотите зашифровать.\n"
54 | "Он должен быть длиной до 400 символов и рекомендуется для лучшего "
55 | "результата использовать символы только из этого списка:\n"
56 | "{allowed_chars} \n"
57 |
58 | #: bot/handlers/buttons.py:40
59 | msgid "https://telegra.ph/Passwords-Decryption-Process-06-02"
60 | msgstr "https://telegra.ph/Process-deshifrovki-parolej-06-09"
61 |
62 | #: bot/handlers/buttons.py:55
63 | msgid ""
64 | "\n"
65 | "Hello, {}\n"
66 | "Let's choose your language\n"
67 | msgstr ""
68 | "\n"
69 | "Привет, {}\n"
70 | "Давай выберем твой язык\n"
71 |
72 | #: bot/handlers/buttons.py:69
73 | msgid "https://telegra.ph/Passcypher-Google-Authenticator-06-02"
74 | msgstr "https://telegra.ph/Passcypher-Ispolzovanie-Google-Authenticator-06-07"
75 |
76 | #: bot/handlers/buttons.py:73 bot/handlers/buttons.py:80
77 | #: bot/handlers/setup_gauth.py:33
78 | msgid "Here you can enable and disable your Google Authenticator settings"
79 | msgstr "Тут вы можете включать и выключать настройки Google Authenticator"
80 |
81 | #: bot/handlers/buttons.py:75 bot/handlers/setup_gauth.py:37
82 | msgid "Turn off"
83 | msgstr "Выключить"
84 |
85 | #: bot/handlers/buttons.py:82 bot/handlers/setup_gauth.py:43
86 | msgid "Turn on"
87 | msgstr "Включить"
88 |
89 | #: bot/handlers/buttons.py:85 bot/handlers/setup_gauth.py:46
90 | msgid "Google Authenticator is not set for you. Press /g_auth_info"
91 | msgstr "Вы еще не настраивали Google Authenticator. Нажмите /g_auth_info"
92 |
93 | #: bot/handlers/decoding.py:27 bot/handlers/decoding.py:89
94 | msgid "Error. Wrong file"
95 | msgstr "Ошибка. Неподдерживаемый файл"
96 |
97 | #: bot/handlers/decoding.py:41 bot/handlers/decoding.py:65
98 | #: bot/handlers/decoding.py:103
99 | msgid "Enter the code from the app"
100 | msgstr "Введите код из приложения"
101 |
102 | #: bot/handlers/decoding.py:54
103 | msgid "Error"
104 | msgstr "Ошибка"
105 |
106 | #: bot/handlers/decoding.py:77 bot/handlers/decoding.py:82
107 | #: bot/handlers/encoding.py:224 bot/handlers/encoding.py:229
108 | msgid "INVALID FILE"
109 | msgstr "Неподдерживаемый файл"
110 |
111 | #: bot/handlers/decoding.py:127
112 | msgid ""
113 | "An error has occurred, you lost the Google authenticator settings\n"
114 | "Please re-configure it once again /g_auth_info"
115 | msgstr ""
116 | "Произошла ошибка, у вас сбилась настройка Google authenticator\n"
117 | "Пожалуйста, настройте его заново /g_auth_info"
118 |
119 | #: bot/handlers/decoding.py:136 bot/handlers/decoding.py:139
120 | #: bot/handlers/setup_gauth.py:134 bot/handlers/setup_gauth.py:145
121 | msgid "Code is incorrect, try again or /cancel"
122 | msgstr "Код неверный, попробуйте снова или отмените /cancel"
123 |
124 | #: bot/handlers/decoding.py:152
125 | msgid ""
126 | "\n"
127 | "Your decoded password is inside citation marks '{password}'"
128 | msgstr ""
129 | "Ваш расшифрованный пароль находится внутри кавычек \n"
130 | "'{password}'"
131 |
132 | #: bot/handlers/encoding.py:63 bot/handlers/encoding.py:133
133 | #: bot/handlers/encoding.py:178
134 | msgid ""
135 | "Error has occurred... Too long phrase. Try to enter a phrase under 400 "
136 | "characters."
137 | msgstr ""
138 | "Ошибочка произошла... Слишком длинный пароль. постарайтесь ввести пароль "
139 | "длиной до 400 символов."
140 |
141 | #: bot/handlers/encoding.py:67 bot/handlers/encoding.py:138
142 | #: bot/handlers/encoding.py:182
143 | msgid "Master Password not found."
144 | msgstr "Мастер пароль был не найден, попробуйте заново"
145 |
146 | #: bot/handlers/encoding.py:73 bot/handlers/encoding.py:147
147 | #: bot/handlers/encoding.py:192
148 | msgid ""
149 | "----------------------------\n"
150 | "ENCRYPTION STARTS HERE\n"
151 | "----------------------------\n"
152 | "{passw}\n"
153 | "----------------------------\n"
154 | "ENCRYPTION ENDS HERE\n"
155 | "----------------------------\n"
156 | "CODE\n"
157 | "{code}\n"
158 | "----------------------------\n"
159 | "\n"
160 | "\n"
161 | "Hint: {hint}\n"
162 | "Save this message wherever you want and forward it to the bot should you "
163 | "need to decode it.\n"
164 | msgstr ""
165 | "----------------------------\n"
166 | "ENCRYPTION STARTS HERE\n"
167 | "----------------------------\n"
168 | "{passw}\n"
169 | "----------------------------\n"
170 | "ENCRYPTION ENDS HERE\n"
171 | "----------------------------\n"
172 | "CODE\n"
173 | "{code}\n"
174 | "----------------------------\n"
175 | "\n"
176 | "\n"
177 | "Подсказка: {hint}\n"
178 | "Сохраните это сообщение где угодно и перешлите боту когда захотите "
179 | "расшифровать свой пароль."
180 |
181 | #: bot/handlers/encoding.py:102 bot/handlers/setup_gauth.py:17
182 | msgid ""
183 | "To encrypt your phrase/file you need to enter a master password each time"
184 | " you want to encrypt or decrypt, or you can enable Google "
185 | "Authenticator and enter one-time codes from your phone only to "
186 | "decrypt your passwords. \n"
187 | "(Master password will be kept in database then) \n"
188 | "\n"
189 | "Please make your choice (you can change it later with command "
190 | "/reset_google_auth\n"
191 | msgstr ""
192 | "Чтобы зашифровать файл/пароль вы должны вводить мастер пароль каждый раз,"
193 | " чтобы зашифровать\\n или расшифровать. \n"
194 | "Но вы можете включить Google Authenticator и вводить одноразовые пароли "
195 | "со своего телефона \\nтолько для расшифровки своих паролей (Но "
196 | "тогда мастер пароль будет храниться в нашей базе данных\n"
197 | "\n"
198 | "Сделайте свой выбор (вы сможете позже отключать эту функцию с помощью "
199 | "команды /reset_google_auth )\n"
200 |
201 | #: bot/handlers/encoding.py:110 bot/handlers/setup_gauth.py:24
202 | msgid "Setup"
203 | msgstr "Начать настройку"
204 |
205 | #: bot/handlers/encoding.py:129
206 | msgid "Password not found."
207 | msgstr "Пароль не был найден, попробуйте заново"
208 |
209 | #: bot/handlers/encoding.py:235
210 | msgid ""
211 | "\n"
212 | "----------------------------\n"
213 | "ENCRYPTION STARTS HERE\n"
214 | "----------------------------\n"
215 | "{passw}\n"
216 | "----------------------------\n"
217 | "ENCRYPTION ENDS HERE\n"
218 | "----------------------------\n"
219 | "CODE\n"
220 | "{code}\n"
221 | "----------------------------\n"
222 | "Hint: {hint}\n"
223 | msgstr ""
224 | "----------------------------\n"
225 | "ENCRYPTION STARTS HERE\n"
226 | "----------------------------\n"
227 | "{passw}\n"
228 | "----------------------------\n"
229 | "ENCRYPTION ENDS HERE\n"
230 | "----------------------------\n"
231 | "CODE\n"
232 | "{code}\n"
233 | "----------------------------\n"
234 | "\n"
235 | "\n"
236 | "Подсказка: {hint}\n"
237 |
238 | #: bot/handlers/main_handlers.py:18 bot/handlers/main_handlers.py:48
239 | #: bot/handlers/main_handlers.py:102 bot/handlers/main_handlers.py:108
240 | msgid "🔒 Encode"
241 | msgstr "🔒 Зашифровать"
242 |
243 | #: bot/handlers/main_handlers.py:19 bot/handlers/main_handlers.py:49
244 | msgid "🔑 Decode"
245 | msgstr "🔑 Расшифровать"
246 |
247 | #: bot/handlers/main_handlers.py:20 bot/handlers/main_handlers.py:50
248 | msgid "ℹ️How to use"
249 | msgstr "ℹ️Как использовать"
250 |
251 | #: bot/handlers/main_handlers.py:21 bot/handlers/main_handlers.py:51
252 | msgid "🇬🇧 Set language"
253 | msgstr "🇷🇺 Сменить язык"
254 |
255 | #: bot/handlers/main_handlers.py:22 bot/handlers/main_handlers.py:52
256 | msgid "🔐 Two step verification"
257 | msgstr "🔐 Двухэтапная верификация"
258 |
259 | #: bot/handlers/main_handlers.py:23 bot/handlers/main_handlers.py:53
260 | msgid "📝 Write a review"
261 | msgstr "📝 Оставить отзыв"
262 |
263 | #: bot/handlers/main_handlers.py:28
264 | msgid ""
265 | "\n"
266 | "Hello, {}\n"
267 | "This bot is designed to encrypt your passwords so you can store them "
268 | "publicly, for example in your Telegram saved messages.\n"
269 | "\n"
270 | "You can choose your language using command /set_language\n"
271 | msgstr ""
272 |
273 | #: bot/handlers/main_handlers.py:57
274 | msgid ""
275 | "Language has changed to 🇬🇧EN\n"
276 | "\n"
277 | "{users} users are using this bot. \n"
278 | "\n"
279 | "{passwords} passwords encrypted.\n"
280 | "{messages} messages received.\n"
281 | "\n"
282 | "Start using this bot: /info"
283 | msgstr ""
284 | "Язык был изменен на 🇷🇺RU\n"
285 | "\n"
286 | "{users} Пользователей используют этого бота.\n"
287 | "{passwords} паролей зашифровано.\n"
288 | "{messages} сообщений обработано.\n"
289 | "\n"
290 | "Начните использовать этого бота: /info\n"
291 | " "
292 |
293 | #: bot/handlers/main_handlers.py:71
294 | msgid ""
295 | "\n"
296 | "{users} users are using this bot. \n"
297 | "\n"
298 | "{passwords} passwords encrypted.\n"
299 | "{messages} messages received.\n"
300 | " "
301 | msgstr ""
302 | "\n"
303 | "{users} Пользователей используют этого бота.\n"
304 | "{passwords} паролей зашифровано.\n"
305 | "{messages} сообщений обработано.\n"
306 | " "
307 |
308 | #: bot/handlers/main_handlers.py:86
309 | msgid ""
310 | "\n"
311 | "Hello, {}\n"
312 | "Firstly, let's choose your language\n"
313 | msgstr ""
314 |
315 | #: bot/handlers/main_handlers.py:104
316 | msgid ""
317 | "\n"
318 | "Looks like the input is invalid...\n"
319 | "To decode your password - forward the message with encoded password you "
320 | "received from bot.\n"
321 | "ᅠ\n"
322 | "Perhaps you wanted to encrypt this message? Click "
323 | msgstr ""
324 | "\n"
325 | "Похоже, что вы ввели неверный запрос...\n"
326 | "\n"
327 | "Для того, чтобы раскодировать - пришлите сообщение, которое вы получили "
328 | "от бота с закодированным паролем. \n"
329 | "ᅠ\n"
330 | "\n"
331 | "Возможно вы хотели зашифровать это сообщение? Нажмите "
332 |
333 | #: bot/handlers/main_handlers.py:109
334 | msgid ""
335 | "\n"
336 | "\n"
337 | "Or setup the language again /set_language"
338 | msgstr ""
339 | "\n"
340 | "\n"
341 | "Или смените язык командой /set_language"
342 |
343 | #: bot/handlers/main_handlers.py:118 bot/handlers/main_handlers.py:123
344 | msgid "Seems like you have an unfinished business..."
345 | msgstr "Похоже, что вы не закончили что-то... (прочитайте предыдущие сообщения)"
346 |
347 | #: bot/handlers/reviews.py:17
348 | msgid ""
349 | "Please, it is important for me to receive a response and advice from you."
350 | "\n"
351 | "How would you change the bot? Any comments are appreciated. \n"
352 | "\n"
353 | "Your comment will be posted anonymously in our channel @pcypher\n"
354 | "Or you can just rate the bot using this link: https://t.me/pcypher/16\n"
355 | msgstr ""
356 | "Для меня очень важно ваше мнение и любой отзыв о боте. \n"
357 | "Что бы вы сделали лучше, что бы вы изменили? Любая помощь оценится. \n"
358 | "\n"
359 | "Ваш комментарий будет опубликован в нашем канале @pcypher абсолютно "
360 | "анонимно.\n"
361 | "\n"
362 | "Или вы можете поставить оценку боту по этой ссылке: "
363 | "https://t.me/pcypher/16"
364 |
365 | #: bot/handlers/reviews.py:24
366 | msgid "Give an advice to the bot"
367 | msgstr "Дать совет боту"
368 |
369 | #: bot/handlers/reviews.py:34 bot/handlers/reviews.py:57
370 | msgid ""
371 | "\n"
372 | "Your advice: \n"
373 | "\n"
374 | "{advice}\n"
375 | "\n"
376 | "Write your advice in the next message.\n"
377 | msgstr ""
378 | "\n"
379 | "Ваш совет: \n"
380 | "\n"
381 | "{advice}\n"
382 | "\n"
383 | "Напишите ваш совет боту в следующем сообщении.\n"
384 |
385 | #: bot/handlers/reviews.py:42 bot/handlers/reviews.py:67
386 | msgid "Cancel"
387 | msgstr "Отмена"
388 |
389 | #: bot/handlers/reviews.py:66
390 | msgid "Publish"
391 | msgstr "Опубликовать отзыв"
392 |
393 | #: bot/handlers/reviews.py:87
394 | msgid "Cancelled"
395 | msgstr "Отменено"
396 |
397 | #: bot/handlers/reviews.py:92
398 | msgid ""
399 | "\n"
400 | "#Reviews Post:\n"
401 | "\n"
402 | "{}\n"
403 | msgstr ""
404 |
405 | #: bot/handlers/setup_gauth.py:55 bot/handlers/setup_gauth.py:92
406 | msgid "That is done"
407 | msgstr "Готово"
408 |
409 | #: bot/handlers/setup_gauth.py:71 bot/handlers/setup_gauth.py:108
410 | msgid "You have already received the Google Authenticator code"
411 | msgstr "Вы уже настраивали Google Authenticator"
412 |
413 | #: bot/handlers/setup_gauth.py:74
414 | msgid ""
415 | "\n"
416 | "Please ensure you have the app installed.\n"
417 | "IOS\n"
419 | "Android"
421 | "\n"
422 | "\n"
423 | "Press continue when you done. After you receive the code - write it down "
424 | "somewhere.\n"
425 | msgstr ""
426 | "\n"
427 | "Для начала убедитесь, что у вас установлено приложение.\n"
428 | "IOS\n"
430 | "Android"
432 | "\n"
433 | "\n"
434 | "Нажмите продолжить когда закончите, после того как получите код - "
435 | "запишите его где нибудь."
436 |
437 | #: bot/handlers/setup_gauth.py:81
438 | msgid "Continue"
439 | msgstr "Продолжить"
440 |
441 | #: bot/handlers/setup_gauth.py:97
442 | msgid "Please press on button to continue or /cancel"
443 | msgstr ""
444 | "Пожалуйста, нажмите продолжить для того, чтобы настроить, или нажмите "
445 | "отмена /cancel"
446 |
447 | #: bot/handlers/setup_gauth.py:112
448 | msgid ""
449 | "\n"
450 | "You will receive a recovery code and a link below.\n"
451 | "IT WILL BE AUTOMATICALLY DELETED AFTER YOU CONFIRM\n"
452 | msgstr ""
453 | "\n"
454 | "Вы получите код для восстановления ниже .\n"
455 | "СООБЩЕНИЕ БУДЕТ УДАЛЕНО ПОСЛЕ ПОДТВЕРЖДЕНИЯ\n"
456 |
457 | #: bot/handlers/setup_gauth.py:120
458 | msgid ""
459 | "Please enter the code from the Google Authenticator\n"
460 | "Pay attention that it updates every 30 sec."
461 | msgstr ""
462 | "Пожалуйста введите код который вы получили в Google Authenticator\n"
463 | "Обратите внимание, что код обновляется каждые 30 сек"
464 |
465 | #: bot/handlers/setup_gauth.py:142
466 | msgid "Confirmation successful, you can proceed. /encode"
467 | msgstr "Успешно подтверждено, можете продолжать. /encode"
468 |
469 |
--------------------------------------------------------------------------------
/locales/uk/LC_MESSAGES/pcypher.po:
--------------------------------------------------------------------------------
1 | # Ukrainian translations for PROJECT.
2 | # Copyright (C) 2019 ORGANIZATION
3 | # This file is distributed under the same license as the PROJECT project.
4 | # FIRST AUTHOR {allowed_chars} \n"
51 | " THE BOT DELETES YOUR MESSAGES WITH PASSWORDS AFTER 10 SECONDS\n"
52 | msgstr ""
53 | "Введіть пароль, котрий бажаєте зашифрувати.\n"
54 | "Він повинен бути довжиною до 400 символів та рекомендується задля кращого"
55 | " результату використовувати символи тільки з цього списку:\n"
56 | " БОТ ВИДАЛЯЄ повідомлення з паролем ЧЕРЕЗ 10 СЕКУНД \n"
57 | "\n"
58 | "{allowed_chars} \n"
59 |
60 | #: bot/handlers/buttons.py:40
61 | msgid "https://telegra.ph/Passwords-Decryption-Process-06-02"
62 | msgstr "https://telegra.ph/Process-deshifrovki-parolej-06-09"
63 |
64 | #: bot/handlers/buttons.py:55
65 | msgid ""
66 | "\n"
67 | "Hello, {}\n"
68 | "Let's choose your language\n"
69 | msgstr ""
70 |
71 | #: bot/handlers/buttons.py:69
72 | msgid "https://telegra.ph/Passcypher-Google-Authenticator-06-02"
73 | msgstr "https://telegra.ph/Passcypher-Ispolzovanie-Google-Authenticator-06-07"
74 |
75 | #: bot/handlers/buttons.py:73 bot/handlers/buttons.py:80
76 | #: bot/handlers/setup_gauth.py:33
77 | msgid "Here you can enable and disable your Google Authenticator settings"
78 | msgstr "Тут ви маєте змогу увімкнути та вимкнути налаштування Google Authenticator"
79 |
80 | #: bot/handlers/buttons.py:75 bot/handlers/setup_gauth.py:37
81 | msgid "Turn off"
82 | msgstr "Вимкнути"
83 |
84 | #: bot/handlers/buttons.py:82 bot/handlers/setup_gauth.py:43
85 | msgid "Turn on"
86 | msgstr "Увімкнути"
87 |
88 | #: bot/handlers/buttons.py:85 bot/handlers/setup_gauth.py:46
89 | msgid "Google Authenticator is not set for you. Press /g_auth_info"
90 | msgstr "Ви ще не налаштовували Google Authenticator. Натисніть /g_auth_info"
91 |
92 | #: bot/handlers/decoding.py:27 bot/handlers/decoding.py:89
93 | msgid "Error. Wrong file"
94 | msgstr "Помилка. Невірний файл."
95 |
96 | #: bot/handlers/decoding.py:41 bot/handlers/decoding.py:65
97 | #: bot/handlers/decoding.py:103
98 | msgid "Enter the code from the app"
99 | msgstr "Введіть код з додатку"
100 |
101 | #: bot/handlers/decoding.py:54
102 | msgid "Error"
103 | msgstr "Помилка"
104 |
105 | #: bot/handlers/decoding.py:77 bot/handlers/decoding.py:82
106 | #: bot/handlers/encoding.py:224 bot/handlers/encoding.py:229
107 | msgid "INVALID FILE"
108 | msgstr "Невірний файл."
109 |
110 | #: bot/handlers/decoding.py:127
111 | msgid ""
112 | "An error has occurred, you lost the Google authenticator settings\n"
113 | "Please re-configure it once again /g_auth_info"
114 | msgstr ""
115 | "Сталася помилка, у вас збилася настройка Google authenticator. \n"
116 | "Будь ласка, налаштуйте його заново. /g_auth_info"
117 |
118 | #: bot/handlers/decoding.py:136 bot/handlers/decoding.py:139
119 | #: bot/handlers/setup_gauth.py:134 bot/handlers/setup_gauth.py:145
120 | msgid "Code is incorrect, try again or /cancel"
121 | msgstr "Хибний код, спробуйте знов або скасуйте /cancel"
122 |
123 | #: bot/handlers/decoding.py:152
124 | msgid ""
125 | "\n"
126 | "Your decoded password is inside citation marks '{password}'"
127 | msgstr ""
128 | "\n"
129 | "Ваш розшифрований пароль знаходиться всередені лапок \n"
130 | "'{password}'\n"
131 | "\n"
132 |
133 | #: bot/handlers/encoding.py:63 bot/handlers/encoding.py:133
134 | #: bot/handlers/encoding.py:178
135 | msgid ""
136 | "Error has occurred... Too long phrase. Try to enter a phrase under 400 "
137 | "characters."
138 | msgstr ""
139 | "Виникла помилочка... Занадто довгий пароль. Будьласка введіть пароль "
140 | "довжиною до 400 символів."
141 |
142 | #: bot/handlers/encoding.py:67 bot/handlers/encoding.py:138
143 | #: bot/handlers/encoding.py:182
144 | msgid "Master Password not found."
145 | msgstr "Майстер пароль не був знайдений"
146 |
147 | #: bot/handlers/encoding.py:73 bot/handlers/encoding.py:147
148 | #: bot/handlers/encoding.py:192
149 | msgid ""
150 | "----------------------------\n"
151 | "ENCRYPTION STARTS HERE\n"
152 | "----------------------------\n"
153 | "{passw}\n"
154 | "----------------------------\n"
155 | "ENCRYPTION ENDS HERE\n"
156 | "----------------------------\n"
157 | "CODE\n"
158 | "{code}\n"
159 | "----------------------------\n"
160 | "\n"
161 | "\n"
162 | "Hint: {hint}\n"
163 | "Save this message wherever you want and forward it to the bot should you "
164 | "need to decode it.\n"
165 | msgstr ""
166 | "----------------------------\n"
167 | "ENCRYPTION STARTS HERE\n"
168 | "----------------------------\n"
169 | "{passw}\n"
170 | "----------------------------\n"
171 | "ENCRYPTION ENDS HERE\n"
172 | "----------------------------\n"
173 | "CODE\n"
174 | "{code}\n"
175 | "----------------------------\n"
176 | "\n"
177 | "Підказка: {hint} \n"
178 | " \n"
179 | "Збережіть цю інформацію де вам зручно, та звертайтесь до бота, коли вам "
180 | "знодиться розшифрувати пароль. \n"
181 |
182 | #: bot/handlers/encoding.py:102 bot/handlers/setup_gauth.py:17
183 | msgid ""
184 | "To encrypt your phrase/file you need to enter a master password each time"
185 | " you want to encrypt or decrypt, or you can enable Google "
186 | "Authenticator and enter one-time codes from your phone only to "
187 | "decrypt your passwords. \n"
188 | "(Master password will be kept in database then) \n"
189 | "\n"
190 | "Please make your choice (you can change it later with command "
191 | "/reset_google_auth\n"
192 | msgstr ""
193 | " Щоб зашифрувати файл/пароль ви повинні вводити мастер пароль кожного "
194 | "разу, щоб зашифрувати\n"
195 | " або розшифрувати.\n"
196 | "Але ви можете увімкнути Google Authenticator та вводити одноразові паролі"
197 | " зі свого телефону \n"
198 | "тільки для розшифровки своїх паролей (Але тоді мастер пароль буде "
199 | "зберігатися в нашій базі даних\n"
200 | "Зробіть свій вибір (ви маєте змогу пізніше відключити цю функцію за "
201 | "допомогою команди /reset_google_auth )"
202 |
203 | #: bot/handlers/encoding.py:110 bot/handlers/setup_gauth.py:24
204 | msgid "Setup"
205 | msgstr "Почати налаштування"
206 |
207 | #: bot/handlers/encoding.py:129
208 | msgid "Password not found."
209 | msgstr "Пароль не був знайдений"
210 |
211 | #: bot/handlers/encoding.py:235
212 | msgid ""
213 | "\n"
214 | "----------------------------\n"
215 | "ENCRYPTION STARTS HERE\n"
216 | "----------------------------\n"
217 | "{passw}\n"
218 | "----------------------------\n"
219 | "ENCRYPTION ENDS HERE\n"
220 | "----------------------------\n"
221 | "CODE\n"
222 | "{code}\n"
223 | "----------------------------\n"
224 | "Hint: {hint}\n"
225 | msgstr ""
226 | "----------------------------\n"
227 | "ENCRYPTION STARTS HERE\n"
228 | "----------------------------\n"
229 | "{passw}\n"
230 | "----------------------------\n"
231 | "ENCRYPTION ENDS HERE\n"
232 | "----------------------------\n"
233 | "CODE\n"
234 | "{code}\n"
235 | "----------------------------\n"
236 | "\n"
237 | "Підказка: {hint} \n"
238 |
239 | #: bot/handlers/main_handlers.py:18 bot/handlers/main_handlers.py:48
240 | #: bot/handlers/main_handlers.py:102 bot/handlers/main_handlers.py:108
241 | msgid "🔒 Encode"
242 | msgstr "🔒 Зашифрувати"
243 |
244 | #: bot/handlers/main_handlers.py:19 bot/handlers/main_handlers.py:49
245 | msgid "🔑 Decode"
246 | msgstr "🔑 Розшифрувати"
247 |
248 | #: bot/handlers/main_handlers.py:20 bot/handlers/main_handlers.py:50
249 | msgid "ℹ️How to use"
250 | msgstr "ℹ️Як використовувати"
251 |
252 | #: bot/handlers/main_handlers.py:21 bot/handlers/main_handlers.py:51
253 | msgid "🇬🇧 Set language"
254 | msgstr "🇺🇦 Змінити мову"
255 |
256 | #: bot/handlers/main_handlers.py:22 bot/handlers/main_handlers.py:52
257 | msgid "🔐 Two step verification"
258 | msgstr "🔐 Двохетапна верифікація"
259 |
260 | #: bot/handlers/main_handlers.py:23 bot/handlers/main_handlers.py:53
261 | msgid "📝 Write a review"
262 | msgstr "📝 Залишити відгук"
263 |
264 | #: bot/handlers/main_handlers.py:28
265 | msgid ""
266 | "\n"
267 | "Hello, {}\n"
268 | "This bot is designed to encrypt your passwords so you can store them "
269 | "publicly, for example in your Telegram saved messages.\n"
270 | "\n"
271 | "You can choose your language using command /set_language\n"
272 | msgstr ""
273 |
274 | #: bot/handlers/main_handlers.py:57
275 | msgid ""
276 | "Language has changed to 🇬🇧EN\n"
277 | "\n"
278 | "{users} users are using this bot. \n"
279 | "\n"
280 | "{passwords} passwords encrypted.\n"
281 | "{messages} messages received.\n"
282 | "\n"
283 | "Start using this bot: /info"
284 | msgstr ""
285 | "Мова була змінена на UA\n"
286 | "\n"
287 | "{users} Користувачів використовують цього бота.\n"
288 | "{passwords} паролів зашифровано.\n"
289 | "{messages} повідомлень оброблено.\n"
290 | "\n"
291 | "Почните користуватися ботом: /info\n"
292 | " "
293 |
294 | #: bot/handlers/main_handlers.py:71
295 | msgid ""
296 | "\n"
297 | "{users} users are using this bot. \n"
298 | "\n"
299 | "{passwords} passwords encrypted.\n"
300 | "{messages} messages received.\n"
301 | " "
302 | msgstr ""
303 | "\n"
304 | "{users} Користувачів використовують цього бота.\n"
305 | "{passwords} паролів зашифровано.\n"
306 | "{messages} повідомлень оброблено.\n"
307 | " "
308 |
309 | #: bot/handlers/main_handlers.py:86
310 | msgid ""
311 | "\n"
312 | "Hello, {}\n"
313 | "Firstly, let's choose your language\n"
314 | msgstr ""
315 |
316 | #: bot/handlers/main_handlers.py:104
317 | msgid ""
318 | "\n"
319 | "Looks like the input is invalid...\n"
320 | "To decode your password - forward the message with encoded password you "
321 | "received from bot.\n"
322 | "ᅠ\n"
323 | "Perhaps you wanted to encrypt this message? Click "
324 | msgstr ""
325 | "\n"
326 | "Схоже, що ви ввели хибний запит...\n"
327 | "Задля того, щоб розкодувати - перешліть повідомлення, котре ви отримали "
328 | "від бота с закодованим паролем. \n"
329 | "ᅠ\n"
330 | "Можливо ви хотіли зашифрувати це повідомлення? Натисніть зашифрувати "
331 | "."
332 |
333 | #: bot/handlers/main_handlers.py:109
334 | msgid ""
335 | "\n"
336 | "\n"
337 | "Or setup the language again /set_language"
338 | msgstr ""
339 | "\n"
340 | "\n"
341 | "Або ви можете змінити свою мову: /set_language"
342 |
343 | #: bot/handlers/main_handlers.py:118 bot/handlers/main_handlers.py:123
344 | msgid "Seems like you have an unfinished business..."
345 | msgstr "Схоже, у вас є незакінчена справа..."
346 |
347 | #: bot/handlers/reviews.py:17
348 | msgid ""
349 | "Please, it is important for me to receive a response and advice from you."
350 | "\n"
351 | "How would you change the bot? Any comments are appreciated. \n"
352 | "\n"
353 | "Your comment will be posted anonymously in our channel @pcypher\n"
354 | "Or you can just rate the bot using this link: https://t.me/pcypher/16\n"
355 | msgstr ""
356 | "Для мене дуже важливо ваша думка та будь-який відгук про бота. Що ви б "
357 | "покращили або змінили? Будь-яка допомога буде цінитись. \n"
358 | "\n"
359 | "Ваш коментарій буде опублікований на нашому каналі @pcypher абсолютно "
360 | "анонімно.\n"
361 | "Або ви можете поставити оцінку боту за цим посиланням: "
362 | "https://t.me/pcypher/16\n"
363 |
364 | #: bot/handlers/reviews.py:24
365 | msgid "Give an advice to the bot"
366 | msgstr "Надати пораду ботові"
367 |
368 | #: bot/handlers/reviews.py:34 bot/handlers/reviews.py:57
369 | msgid ""
370 | "\n"
371 | "Your advice: \n"
372 | "\n"
373 | "{advice}\n"
374 | "\n"
375 | "Write your advice in the next message.\n"
376 | msgstr ""
377 | "\n"
378 | "Ваша порада: \n"
379 | "\n"
380 | "{advice}\n"
381 | "\n"
382 | "Напишіть вашу пораду ботові у наступному повідомленні.\n"
383 |
384 | #: bot/handlers/reviews.py:42 bot/handlers/reviews.py:67
385 | msgid "Cancel"
386 | msgstr "Скасувати"
387 |
388 | #: bot/handlers/reviews.py:66
389 | msgid "Publish"
390 | msgstr "Опубліковати відгук"
391 |
392 | #: bot/handlers/reviews.py:87
393 | msgid "Cancelled"
394 | msgstr "Скасовано"
395 |
396 | #: bot/handlers/reviews.py:92
397 | msgid ""
398 | "\n"
399 | "#Reviews Post:\n"
400 | "\n"
401 | "{}\n"
402 | msgstr ""
403 |
404 | #: bot/handlers/setup_gauth.py:55 bot/handlers/setup_gauth.py:92
405 | msgid "That is done"
406 | msgstr "Готово"
407 |
408 | #: bot/handlers/setup_gauth.py:71 bot/handlers/setup_gauth.py:108
409 | msgid "You have already received the Google Authenticator code"
410 | msgstr "Ви вже налаштовували Google Authenticator"
411 |
412 | #: bot/handlers/setup_gauth.py:74
413 | msgid ""
414 | "\n"
415 | "Please ensure you have the app installed.\n"
416 | "IOS\n"
418 | "Android"
420 | "\n"
421 | "\n"
422 | "Press continue when you done. After you receive the code - write it down "
423 | "somewhere.\n"
424 | msgstr ""
425 | "\n"
426 | "Зпочатку переконайтесь, що в вас встановлений додаток.\n"
427 | "IOS\n"
429 | "Android"
431 | "\n"
432 | "\n"
433 | "Натисніть продовжити коли закінчите, після того як отрумаєте код - "
434 | "запишіть його де-небудь."
435 |
436 | #: bot/handlers/setup_gauth.py:81
437 | msgid "Continue"
438 | msgstr "Продовжити"
439 |
440 | #: bot/handlers/setup_gauth.py:97
441 | msgid "Please press on button to continue or /cancel"
442 | msgstr ""
443 | "Будь ласка, натисніть продовжити для того, щоб налаштувати, або натисніть"
444 | " для скасування /cancel"
445 |
446 | #: bot/handlers/setup_gauth.py:112
447 | msgid ""
448 | "\n"
449 | "You will receive a recovery code and a link below.\n"
450 | "IT WILL BE AUTOMATICALLY DELETED AFTER YOU CONFIRM\n"
451 | msgstr ""
452 | "\n"
453 | "Ви отримуєте код для відновлення нижче .\n"
454 | "ПОВІДОМЛЕННЯ БУДЕ ВИДАЛЕНЕ ПІСЛЯ ПІДТВЕРДЖЕННЯ\n"
455 |
456 | #: bot/handlers/setup_gauth.py:120
457 | msgid ""
458 | "Please enter the code from the Google Authenticator\n"
459 | "Pay attention that it updates every 30 sec."
460 | msgstr ""
461 | "Будьласка введить код котрий ви отримали в Google Authenticator\n"
462 | "Зверніть увагу, що код оновлюється кожні 30 сек"
463 |
464 | #: bot/handlers/setup_gauth.py:142
465 | msgid "Confirmation successful, you can proceed. /encode"
466 | msgstr "Успішно підтверджено, продовжуйте. /encode"
467 |
468 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.