Implement password authentication

This commit is contained in:
Stanislav Mykhailenko 2023-01-31 16:59:00 +02:00
parent 9feb845d3c
commit 758302bb2a
GPG key ID: 1E95E66A9C9D6A36
4 changed files with 53 additions and 26 deletions

2
.gitignore vendored
View file

@ -128,4 +128,4 @@ dmypy.json
# Pyre type checker # Pyre type checker
.pyre/ .pyre/
token.txt config.py

View file

@ -2,9 +2,6 @@
This program is a PC kill switch Telegram bot. It is a project for New Generation. This program is a PC kill switch Telegram bot. It is a project for New Generation.
## Security notice
This program provides no access control, so anyone knowing the bot username is able to use it.
## Features ## Features
- disabling and re-enabling keyboard and mouse input - disabling and re-enabling keyboard and mouse input
- locking the screen - locking the screen
@ -17,7 +14,7 @@ This program provides no access control, so anyone knowing the bot username is a
- works on Windows only - works on Windows only
## Usage ## Usage
Before starting the bot, its token must be put into token.txt file with no newlines. Administrator privileges are required so that the bot is able to disable input and format partitions. Once the bot is started, send /start to its account on Telegram to see what can be done. Before starting the bot, copy config-example.py file to config.py and put the password and the token. Administrator privileges are required so that the bot is able to disable input and format partitions. Once the bot is started, send /start to its account on Telegram and enter the password to see what can be done.
## Licensing ## Licensing
All code in this repository is Unlicensed, see UNLICENSE. All code in this repository is Unlicensed, see UNLICENSE.

11
config-example.py Normal file
View file

@ -0,0 +1,11 @@
# Project: Telegram PC kill switch bot
# Author: Stanislav Mykhailenko
# License: Unlicense
# This file contains an example config for the program
# Telegram bot token
token = "put your token here"
# Bot password
master_password = "put your password here"

45
tg.py
View file

@ -4,6 +4,7 @@
# This file contains Telegram interactions # This file contains Telegram interactions
from config import *
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import Application, CommandHandler, ContextTypes, ConversationHandler, filters, MessageHandler from telegram.ext import Application, CommandHandler, ContextTypes, ConversationHandler, filters, MessageHandler
from payload import * from payload import *
@ -16,14 +17,14 @@ logging.basicConfig(
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
ACTION, FORMAT, MESSAGE = range(3) PASSWORD, ACTION, FORMAT, MESSAGE = range(4)
def getToken():
with open(os.path.realpath(os.path.dirname(__file__)) + '/' + 'token.txt', 'r') as file:
return file.read()
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
await update.message.reply_text("Enter password.")
return PASSWORD
async def show_keyboard(update: Update):
reply_keyboard = [["Enable input", "Disable input", "Lock screen", "Format volumes", "Play message"]] reply_keyboard = [["Enable input", "Disable input", "Lock screen", "Format volumes", "Play message"]]
await update.message.reply_text( await update.message.reply_text(
@ -33,8 +34,20 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
), ),
) )
async def password(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user = update.message.from_user
if update.message.text == master_password:
logger.info("User %s logged in.", user.first_name)
await show_keyboard(update)
return ACTION return ACTION
logger.info("User %s failed to log in.", user.first_name)
await update.message.reply_text("Wrong password entered, please try again.")
return PASSWORD
async def action(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: async def action(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user = update.message.from_user user = update.message.from_user
@ -43,17 +56,20 @@ async def action(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
logger.info("Got a request from %s to enable input.", user.first_name) logger.info("Got a request from %s to enable input.", user.first_name)
enableInput() enableInput()
await update.message.reply_text("Input enabled.", reply_markup=ReplyKeyboardRemove()) await update.message.reply_text("Input enabled.", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END await show_keyboard(update)
return ACTION
case "Disable input": case "Disable input":
logger.info("Got a request from %s to disable input.", user.first_name) logger.info("Got a request from %s to disable input.", user.first_name)
disableInput() disableInput()
await update.message.reply_text("Input disabled.", reply_markup=ReplyKeyboardRemove()) await update.message.reply_text("Input disabled.", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END await show_keyboard(update)
return ACTION
case "Lock screen": case "Lock screen":
logger.info("Got a request from %s to lock screen.", user.first_name) logger.info("Got a request from %s to lock screen.", user.first_name)
lockScreen() lockScreen()
await update.message.reply_text("Screen locked.", reply_markup=ReplyKeyboardRemove()) await update.message.reply_text("Screen locked.", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END await show_keyboard(update)
return ACTION
case "Format volumes": case "Format volumes":
logger.info("Got a request from %s to format volumes.", user.first_name) logger.info("Got a request from %s to format volumes.", user.first_name)
await update.message.reply_text("Please type a space-separated list of the volumes you want to format.", reply_markup=ReplyKeyboardRemove()) await update.message.reply_text("Please type a space-separated list of the volumes you want to format.", reply_markup=ReplyKeyboardRemove())
@ -70,7 +86,8 @@ async def format(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
Thread(target=formatVolumes,args=(update.message.text.split(),)).start() Thread(target=formatVolumes,args=(update.message.text.split(),)).start()
await update.message.reply_text("Command to format the volumes sent.") await update.message.reply_text("Command to format the volumes sent.")
return ConversationHandler.END await show_keyboard(update)
return ACTION
async def message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: async def message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user = update.message.from_user user = update.message.from_user
@ -78,21 +95,23 @@ async def message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
Thread(target=playMessage,args=(update.message.text,)).start() Thread(target=playMessage,args=(update.message.text,)).start()
await update.message.reply_text("Command to play the message sent.") await update.message.reply_text("Command to play the message sent.")
return ConversationHandler.END await show_keyboard(update)
return ACTION
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user = update.message.from_user user = update.message.from_user
logger.info("User %s canceled the conversation.", user.first_name) logger.info("User %s cancelled the conversation.", user.first_name)
await update.message.reply_text("Request cancelled.", reply_markup=ReplyKeyboardRemove()) await update.message.reply_text("Request cancelled.", reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END return ConversationHandler.END
def startBot(): def startBot():
application = Application.builder().token(getToken()).build() application = Application.builder().token(token).build()
conv_handler = ConversationHandler( conv_handler = ConversationHandler(
entry_points=[CommandHandler("start", start)], entry_points=[CommandHandler("start", start)],
states={ states={
PASSWORD: [MessageHandler(filters.TEXT & ~filters.COMMAND, password)],
ACTION: [MessageHandler(filters.Regex("^(Enable input|Disable input|Lock screen|Format volumes|Play message)$"), action)], ACTION: [MessageHandler(filters.Regex("^(Enable input|Disable input|Lock screen|Format volumes|Play message)$"), action)],
FORMAT: [MessageHandler(filters.TEXT & ~filters.COMMAND, format)], FORMAT: [MessageHandler(filters.TEXT & ~filters.COMMAND, format)],
MESSAGE: [MessageHandler(filters.TEXT & ~filters.COMMAND, message)], MESSAGE: [MessageHandler(filters.TEXT & ~filters.COMMAND, message)],