1
0
mirror of https://gitlab.com/octospacc/WinDog.git synced 2025-03-06 20:27:37 +01:00

Add commands exec eval level and some fixes

This commit is contained in:
octospacc 2023-07-07 18:14:18 +02:00
parent a54ebb61f2
commit fcd444bf0f
5 changed files with 223 additions and 96 deletions

4
.gitignore vendored

@ -1,2 +1,4 @@
Database.json
Dump.txt
Config.py
*.pyc
*.pyc

@ -1,13 +1,13 @@
{
"start": [
"Hi {user.mention_markdown_v2()}!"
"*Hi* {user.mention_markdown_v2()}*!*"
],
"help": [
"There's no one around to help (yet)."
"*There's no one around to help (yet).*"
],
"echo": {
"empty": [
"Echo what? Give me something to repeat."
"*Echo what? Give me something to repeat.*"
]
},
"wish": {
@ -15,7 +15,7 @@
"*You wished for nothing! ✨*\n\n_Nothing happens..._"
],
"done": [
"*Your wish has been cast! ✨*\n\n_Chance of success: {0}%_"
"*Your wish has been cast! ✨*\n\n_Chance of success: *{Percent}%*._"
]
},
"hug": {
@ -27,5 +27,22 @@
"others": [
"*{0} hugs {1} tightly... :3*"
]
}
}
},
"level": {
"empty": [
"Check what's your level of something.\n\n*Usage*: {Cmd} <Thing>."
],
"done": [
"_Your level of *{Thing}* is... *{Percent}%*._"
]
},
"hash": [
"*Usage*: {0} <Algorithm> <Text to Hash>.\n\n*Available algorithms*: {1}."
],
"eval": [
"This feature is not implemented [Security Issue]."
],
"time": [
"Local time: *{0}*."
]
}

@ -1,6 +1,6 @@
{
"start": [
"Ciao {user.mention_markdown_v2()}!"
"*Ciao* {0}*!*"
],
"help": [
"*Non c'è nessuno qui ad aiutarti (per ora).*"
@ -15,7 +15,15 @@
"*Non hai desiderato nulla! ✨*\n\n_Non succede niente..._"
],
"done": [
"*Il tuo desiderio è stato espresso! ✨*\n\n_Probabilità che si avveri: {0}%_"
"*Il tuo desiderio è stato espresso! ✨*\n\n_Probabilità che si avveri: *{Percent}%*._"
]
},
"level": {
"empty": [
"Controlla il tuo livello di qualcosa.\n\n*Uso*: {Cmd} <Cosa>."
],
"done": [
"_Il tuo livello di *{Thing}* è... *{Percent}%*._"
]
},
"hug": {

7
StartWinDog Executable file

@ -0,0 +1,7 @@
#!/bin/bash
ScriptPath=$(realpath $0)
ScriptDir=$(dirname $ScriptPath)
cd $ScriptDir
python3 WinDog.py

267
WinDog.py

@ -1,36 +1,82 @@
#!/usr/bin/env python3
# =================================== #
# WinDog multi-purpose chatbot
# Licensed under AGPLv3 by OctoSpacc
# =================================== #
# ================================== #
# WinDog multi-purpose chatbot #
# Licensed under AGPLv3 by OctoSpacc #
# ================================== #
import json
import json, hashlib, re, time, subprocess
from os import listdir
from random import choice, randint
from types import SimpleNamespace
from telegram import Update, ForceReply, Bot
from telegram.utils.helpers import escape_markdown
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackContext
from Config import *
Private = {}
Locale = {}
Db = {"Chats": {}}
Locale = {"Fallback": {}}
def CharEscape(String, Escape=''):
def SetupDb() -> None:
global Db
try:
with open('Database.json', 'r') as File:
Db = json.load(File)
except Exception:
pass
def SetupLocale() -> None:
global Locale
for File in listdir('./Locale'):
Lang = File.split('.')[0]
try:
with open(f'./Locale/{File}') as File:
Locale[Lang] = json.load(File)
except Exception:
print(f'Cannot load {Lang} locale, exiting.')
raise
exit(1)
for Key in Locale[DefaultLang]:
Locale['Fallback'][Key] = Locale[DefaultLang][Key]
for Lang in Locale:
for Key in Locale[Lang]:
if not Key in Locale['Fallback']:
Locale['Fallback'][Key] = Locale[Lang][Key]
def __(Key:str, Lang:str=DefaultLang):
Set = None
Key = Key.split('.')
try:
Set = Locale.Locale[Lang]
for El in Key:
Set = Set[El]
except Exception:
Set = Locale.Locale['Fallback']
for El in Key:
Set = Set[El]
return Set
Locale['__'] = __
Locale['Locale'] = Locale
Locale = SimpleNamespace(**Locale)
def CharEscape(String, Escape='') -> str:
if Escape == 'MARKDOWN':
return escape_markdown(String, version=2)
elif Escape == 'MARKDOWN_SPEECH':
for c in '.!_()[]<>':
String = String.replace(c, '\\'+c)
return String
else:
if Escape == 'MARKDOWN_SPEECH':
Escape = '+-_.!()[]{}<>'
elif Escape == 'MARKDOWN_SPEECH_FORMAT':
Escape = '+-_.!()[]<>'
for c in Escape:
String = String.replace(c, '\\'+c)
return String
return String
def CommandFilter(Message):
return Message.lower().split(' ')[0][1:].split('@')[0]
def GetRawTokens(Text:str) -> list:
return Text.strip().replace('\t', ' ').replace(' ', ' ').replace(' ', ' ').split(' ')
def RandPercent():
def CmdFilter(Msg) -> str:
return Msg.lower().split(' ')[0][1:].split('@')[0]
def RandPercent() -> int:
Num = randint(0,100)
if Num == 100:
Num = str(Num) + '\.00'
@ -38,77 +84,85 @@ def RandPercent():
Num = str(Num) + '\.' + str(randint(0,9)) + str(randint(0,9))
return Num
def start(update:Update, context:CallbackContext) -> None:
def cStart(update:Update, context:CallbackContext) -> None:
if CmdRestrict(update):
user = update.effective_user
update.message.reply_markdown_v2(
fr'Hi {user.mention_markdown_v2()}\!',
#reply_markup=ForceReply(selective=True),
)
def help(update:Update, context:CallbackContext) -> None:
if CmdRestrict(update):
update.message.reply_markdown_v2(
CharEscape(choice(Locale[Lang]['help']), '.!()'),
CharEscape(choice(Locale.__('start')), 'MARKDOWN_SPEECH').format(user.mention_markdown_v2()),
reply_to_message_id=update.message.message_id)
def echo(update:Update, context:CallbackContext) -> None:
def cHelp(update:Update, context:CallbackContext) -> None:
if CmdRestrict(update):
Message = update.message.text
if len(Message.split(' ')) < 2:
Text = CharEscape(choice(Locale[Lang]['echo']['empty']), '.!')
update.message.reply_markdown_v2(
Text,
reply_to_message_id=update.message.message_id)
else:
Text = Message[len(Message.split(' ')[0])+1:]
update.message.reply_markdown_v2(
CharEscape(choice(Locale.__('help')), 'MARKDOWN_SPEECH'),
reply_to_message_id=update.message.message_id)
def cConfig(update:Update, context:CallbackContext) -> None:
pass
def cEcho(update:Update, context:CallbackContext) -> None:
if CmdRestrict(update):
Msg = update.message.text
if len(Msg.split(' ')) >= 2:
Text = Msg[len(Msg.split(' ')[0])+1:]
update.message.reply_text(
Text,
reply_to_message_id=update.message.message_id)
else:
Text = CharEscape(choice(Locale.__('echo.empty')), '.!')
update.message.reply_markdown_v2(
Text,
reply_to_message_id=update.message.message_id)
def ping(update:Update, context:CallbackContext) -> None:
def cPing(update:Update, context:CallbackContext) -> None:
if CmdRestrict(update):
update.message.reply_markdown_v2(
'*Pong\!*',
reply_to_message_id=update.message.message_id)
def wish(update:Update, context:CallbackContext) -> None:
def percenter(update:Update, context:CallbackContext) -> None:
if CmdRestrict(update):
if len(update.message.text.split(' ')) < 2:
Text = choice(Locale[Lang]['wish']['empty'])
Msg = update.message.text
Key = CmdFilter(Msg)
Toks = GetRawTokens(Msg)
Thing = Key.join(Msg.split(Key)[1:]).strip()
if len(Toks) >= 2:
Text = choice(Locale.__(f'{Key}.done'))
else:
Text = choice(Locale[Lang]['wish']['done'])
Text = choice(Locale.__(f'{Key}.empty'))
update.message.reply_markdown_v2(
CharEscape(Text, '.!').format(RandPercent()),
CharEscape(Text, '.!').format(Cmd=Toks[0], Percent=RandPercent(), Thing=Thing),
reply_to_message_id=update.message.message_id)
def multifun(update:Update, context:CallbackContext) -> None:
if CmdRestrict(update):
Key = CommandFilter(update.message.text)
ReplyToMessage = update.message.message_id
Key = CmdFilter(update.message.text)
ReplyToMsg = update.message.message_id
if update.message.reply_to_message:
ReplyFromUID = update.message.reply_to_message.from_user.id
if ReplyFromUID == TGID and 'bot' in Locale[Lang][Key]:
Text = CharEscape(choice(Locale[Lang][Key]['bot']), 'MARKDOWN_SPEECH')
elif ReplyFromUID == update.message.from_user.id and 'self' in Locale[Lang][Key]:
if ReplyFromUID == TGID and 'bot' in Locale.__(Key):
Text = CharEscape(choice(Locale.__(f'{Key}.bot')), 'MARKDOWN_SPEECH')
elif ReplyFromUID == update.message.from_user.id and 'self' in Locale.__(Key):
FromUName = CharEscape(update.message.from_user.first_name, 'MARKDOWN')
Text = CharEscape(choice(Locale[Lang][Key]['self']), 'MARKDOWN_SPEECH').format(FromUName)
Text = CharEscape(choice(Locale.__(f'{Key}.self')), 'MARKDOWN_SPEECH').format(FromUName)
else:
if 'others' in Locale[Lang][Key]:
if 'others' in Locale.__(Key):
FromUName = CharEscape(update.message.from_user.first_name, 'MARKDOWN')
ToUName = CharEscape(update.message.reply_to_message.from_user.first_name, 'MARKDOWN')
Text = CharEscape(choice(Locale[Lang][Key]['others']), 'MARKDOWN_SPEECH').format(FromUName,ToUName)
ReplyToMessage = update.message.reply_to_message.message_id
Text = CharEscape(choice(Locale.__(f'{Key}.others')), 'MARKDOWN_SPEECH').format(FromUName,ToUName)
ReplyToMsg = update.message.reply_to_message.message_id
else:
if 'empty' in Locale[Lang][Key]:
Text = CharEscape(choice(Locale[Lang][Key]['empty']), 'MARKDOWN_SPEECH')
update.message.reply_markdown_v2(
Text,
reply_to_message_id=ReplyToMessage)
if 'empty' in Locale.__(Key):
Text = CharEscape(choice(Locale.__(f'{Key}.empty')), 'MARKDOWN_SPEECH')
update.message.reply_markdown_v2(Text, reply_to_message_id=ReplyToMsg)
def cUnsplash(update:Update, context:CallbackContext) -> None:
pass
def filters(update:Update, context:CallbackContext) -> None:
pass
if Debug and Dumper:
with open('Dump.txt', 'a') as File:
File.write(f'[{time.ctime()}] [{int(time.time())}] [{update.message.chat.id}] [{update.message.message_id}] [{update.message.from_user.id}] {update.message.text}\n')
'''
if CmdRestrict(update):
ChatID = update.message.chat.id
@ -130,51 +184,90 @@ def setfilter(update:Update, context:CallbackContext) -> None:
Private['Chats'][ChatID]['Filters'][update.message.text] = {'Text':0}
'''
def CmdRestrict(update):
def cTime(update:Update, context:CallbackContext) -> None:
update.message.reply_markdown_v2(
CharEscape(choice(Locale.__('time')).format(time.ctime().replace(' ', ' ')), 'MARKDOWN_SPEECH'),
reply_to_message_id=update.message.message_id)
def cHash(update:Update, context:CallbackContext) -> None:
if CmdRestrict(update):
Msg = update.message.text
Toks = GetRawTokens(Msg)
if len(Toks) >= 3 and Toks[1] in hashlib.algorithms_available:
Alg = Toks[1]
Caption = hashlib.new(Alg, Alg.join(Msg.split(Alg)[1:]).strip().encode()).hexdigest()
else:
Caption = CharEscape(choice(Locale.__('hash')).format(Toks[0], hashlib.algorithms_available), 'MARKDOWN_SPEECH')
update.message.reply_markdown_v2(Caption, reply_to_message_id=update.message.message_id)
def cEval(update:Update, context:CallbackContext) -> None:
if CmdRestrict(update):
update.message.reply_markdown_v2(
CharEscape(choice(Locale.__('eval')), 'MARKDOWN_SPEECH'),
reply_to_message_id=update.message.message_id)
def cExec(update:Update, context:CallbackContext) -> None:
if CmdRestrict(update):
Toks = GetRawTokens(update.message.text)
if len(Toks) >= 2 and Toks[1].lower() in ('date', 'neofetch', 'uptime'):
Caption = '```' + CharEscape(re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])').sub('', subprocess.run(('sh', '-c', Toks[1].lower()), stdout=subprocess.PIPE).stdout.decode()) , 'MARKDOWN') + '```',
update.message.reply_markdown_v2(
# <https://stackoverflow.com/a/14693789>
'```' + CharEscape( re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])').sub('', subprocess.run(('sh', '-c', Toks[1].lower()),
stdout=subprocess.PIPE).stdout.decode()) , 'MARKDOWN') + '```',
reply_to_message_id=update.message.message_id)
else:
update.message.reply_markdown_v2(
CharEscape(choice(Locale.__('eval')), 'MARKDOWN_SPEECH'),
reply_to_message_id=update.message.message_id)
#def CmdArgs(Msg:str, Cfg:tuple=None):
# Args = []
# Msg = Msg.strip().replace('\t', ' ')
# if Cfg:
# for i in Cfg:
# Args += [Msg.replace(' ', ' ').replace(' ', ' ').split(' ')[:i]]
# Msg = Msg
# else:
# return Msg.replace(' ', ' ').replace(' ', ' ').split(' ')
def CmdRestrict(update) -> bool:
if not TGRestrict:
return True
else:
if TGRestrict == 'Whitelist':
if TGRestrict.lower() == 'whitelist':
if update.message.chat.id in TGWhitelist:
return True
return False
def main() -> None:
global Private, Locale
#def SendMsg(Data, context):
# pass
try:
with open('Private.json', 'r') as File:
Private = json.load(File)
except Exception:
Private = {}
if 'Chats' not in Private:
Private['Chats'] = {}
try:
with open('Locale/{0}.json'.format(Lang)) as File:
Locale[Lang] = json.load(File)
except Exception:
print('Cannot load {0} locale, exiting'.format(Lang))
raise
exit(1)
def Main() -> None:
SetupDb()
SetupLocale()
#Private['Chats'].update({update.message.chat.id:{}})
updater = Updater(TGToken)
dispatcher = updater.dispatcher
dispatcher.add_handler(CommandHandler('start', start))
dispatcher.add_handler(CommandHandler('help', help))
dispatcher.add_handler(CommandHandler('echo', echo))
dispatcher.add_handler(CommandHandler('ping', ping))
dispatcher.add_handler(CommandHandler('wish', wish))
dispatcher.add_handler(CommandHandler('hug', multifun))
dispatcher.add_handler(CommandHandler('pat', multifun))
dispatcher.add_handler(CommandHandler('poke', multifun))
dispatcher.add_handler(CommandHandler('cuddle', multifun))
dispatcher.add_handler(CommandHandler('floor', multifun))
dispatcher.add_handler(CommandHandler('hands', multifun))
dispatcher.add_handler(CommandHandler('sessocto', multifun))
dispatcher.add_handler(CommandHandler('start', cStart))
dispatcher.add_handler(CommandHandler('config', cConfig))
dispatcher.add_handler(CommandHandler('help', cHelp))
dispatcher.add_handler(CommandHandler('echo', cEcho))
dispatcher.add_handler(CommandHandler('ping', cPing))
dispatcher.add_handler(CommandHandler('time', cTime))
dispatcher.add_handler(CommandHandler('hash', cHash))
dispatcher.add_handler(CommandHandler('eval', cEval))
dispatcher.add_handler(CommandHandler('exec', cExec))
dispatcher.add_handler(CommandHandler('unsplash', cUnsplash))
for Cmd in ('wish', 'level'):
dispatcher.add_handler(CommandHandler(Cmd, percenter))
for Cmd in ('hug', 'pat', 'poke', 'cuddle', 'floor', 'hands', 'sessocto'):
dispatcher.add_handler(CommandHandler(Cmd, multifun))
#dispatcher.add_handler(CommandHandler('setfilter', setfilter))
dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command, filters))
@ -183,5 +276,5 @@ def main() -> None:
updater.idle()
if __name__ == '__main__':
main()
Main()
print('Closing WinDog...')