Skip to content

Commit

Permalink
1.0.9
Browse files Browse the repository at this point in the history
  • Loading branch information
onlive1337 committed Dec 9, 2024
1 parent 766531d commit ba6f92f
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 66 deletions.
10 changes: 5 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
[1.0.8] - 2024-11-23
[1.0.9] - 2024-12-09

RU:

Исправлено:

Не администраторы чата могли менять настройки чата
Баги с двоичными запросами (аля 20к сум и 20к рублей)

Чуть чуть почистил код
Баги с парсированием текста с запятой

EN:

Fixed:

Non-administrators of the chat could change chat room settings
Bugs with binary queries (aka 20k sum and 20k rubles)

Cleaned up the code a bit
Bugs with parsing text with comma
2 changes: 1 addition & 1 deletion config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
LOG_CHAT_ID = "-4558354811"
ADMIN_IDS = [810587766]
USER_DATA_FILE = 'user_data.json'
CURRENT_VERSION = "1.0.8"
CURRENT_VERSION = "1.0.9"

CACHE_EXPIRATION_TIME = 600

Expand Down
69 changes: 19 additions & 50 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,15 +395,14 @@ async def handle_message(message: types.Message):
await cmd_stats(message)
return

requests = re.split(r'[,;]|\s+и\s+|\s+and\s+', message.text)
requests = re.split(r';|\s+и\s+|\s+and\s+', message.text)
valid_requests = []

for request in requests:
request = re.sub(r'(\d+),(\d{3})', r'\1\2', request)
parsed_result = parse_amount_and_currency(request)
if parsed_result is not None:
amount, currency = parsed_result
if amount is not None and currency is not None:
valid_requests.append((amount, currency))
if parsed_result[0] is not None and parsed_result[1] is not None:
valid_requests.append(parsed_result)

if valid_requests:
if len(valid_requests) > 1:
Expand Down Expand Up @@ -507,96 +506,66 @@ async def process_multiple_conversions(message: types.Message, requests: List[Tu
async def process_conversion(message: types.Message, amount: float, from_currency: str):
user_id = message.from_user.id
chat_id = message.chat.id
user_data.update_user_data(user_id)
user_lang = user_data.get_user_language(user_id)
logger.info(f"Processing conversion: {amount} {from_currency} for user {user_id} in chat {chat_id}")

try:
if amount <= 0:
await message.answer(LANGUAGES[user_lang].get('negative_or_zero_amount', "The result of the calculation is negative or zero. Please enter a positive amount."))
return

if amount > 1e100 or amount < -1e100:
await message.answer(LANGUAGES[user_lang].get('number_too_large', "The number is too large to process."))
await message.answer(LANGUAGES[user_lang].get('negative_or_zero_amount'))
return

rates = await get_exchange_rates()
if not rates:
logger.error(f"Failed to get exchange rates for user {user_id}")
await message.answer(LANGUAGES[user_lang]['error'])
return

if message.chat.type in ['group', 'supergroup']:
user_data.update_chat_cache(chat_id)
user_currencies = user_data.get_chat_currencies(chat_id)
user_crypto = user_data.get_chat_crypto(chat_id)
else:
user_currencies = user_data.get_user_currencies(user_id)
user_crypto = user_data.get_user_crypto(user_id)

if not user_currencies and not user_crypto:
no_currencies_message = LANGUAGES[user_lang].get('select_currencies_full_message',
"You haven't selected any currencies. Please go to bot settings to select currencies for conversion.")
await message.answer(no_currencies_message)
return

response = f"{format_large_number(amount)} {ALL_CURRENCIES.get(from_currency, '')} {from_currency}\n\n"

fiat_conversions = []
crypto_conversions = []
response_parts = []
response_parts.append(f"{format_large_number(amount)} {ALL_CURRENCIES.get(from_currency, '')} {from_currency}\n")

if user_currencies:
response_parts.append(f"\n{LANGUAGES[user_lang]['fiat_currencies']}")
fiat_conversions = []
for to_cur in user_currencies:
if to_cur != from_currency:
try:
converted = convert_currency(amount, from_currency, to_cur, rates)
conversion_line = f"{format_large_number(converted)} {ALL_CURRENCIES.get(to_cur, '')} {to_cur}"
fiat_conversions.append(conversion_line)
except KeyError:
logger.warning(f"Conversion failed for {to_cur}. It might not be in the rates.")
except OverflowError:
fiat_conversions.append(f"Overflow {ALL_CURRENCIES.get(to_cur, '')} {to_cur}")
continue
response_parts.append("<blockquote expandable>" + "\n".join(fiat_conversions) + "</blockquote>")

if user_crypto:
response_parts.append(f"\n\n{LANGUAGES[user_lang]['cryptocurrencies_output']}")
crypto_conversions = []
for to_cur in user_crypto:
if to_cur != from_currency:
try:
converted = convert_currency(amount, from_currency, to_cur, rates)
conversion_line = f"{format_large_number(converted, True)} {ALL_CURRENCIES.get(to_cur, '')} {to_cur}"
crypto_formatted = " ".join(conversion_line.split()[:2])
crypto_conversions.append(crypto_formatted)
conversion_line = f"{format_large_number(converted, True)} {to_cur}"
crypto_conversions.append(conversion_line)
except KeyError:
logger.warning(f"Conversion failed for {to_cur}. It might not be in the rates.")
except OverflowError:
crypto_conversions.append(f"Overflow {ALL_CURRENCIES.get(to_cur, '')} {to_cur}")

if fiat_conversions:
response += f"<b>{LANGUAGES[user_lang]['fiat_currencies']}</b>\n"
response += "<blockquote expandable>\n"
response += "\n".join(fiat_conversions)
response += "</blockquote>\n\n"

if crypto_conversions:
response += f"<b>{LANGUAGES[user_lang]['cryptocurrencies_output']}</b>\n"
response += "<blockquote expandable>\n"
response += "\n".join(crypto_conversions)
response += "</blockquote>"
continue
response_parts.append("<blockquote expandable>" + "\n".join(crypto_conversions) + "</blockquote>")

kb = InlineKeyboardBuilder()
kb.button(text=LANGUAGES[user_lang].get('delete_button', "Delete"), callback_data="delete_conversion")

logger.info(f"Sending conversion response for {amount} {from_currency} to user {user_id} in chat {chat_id}")
final_response = "".join(response_parts).strip()

await message.reply(
text=response,
text=final_response,
reply_markup=kb.as_markup(),
parse_mode="HTML"
)
except OverflowError:
await message.answer(LANGUAGES[user_lang].get('number_too_large', "The number is too large to process."))
except Exception as e:
logger.error(f"Error in process_conversion for user {user_id}: {e}")
logger.exception("Full traceback:")
await message.answer(LANGUAGES[user_lang]['error'])

async def process_about(callback_query: CallbackQuery):
Expand Down
20 changes: 10 additions & 10 deletions utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ def parse_amount_and_currency(text: str) -> Tuple[Optional[float], Optional[str]

if not text:
return None, None

new_text = text.replace(',', '')

replacements = {
'кк': '*1000000',
Expand All @@ -126,12 +128,9 @@ def parse_amount_and_currency(text: str) -> Tuple[Optional[float], Optional[str]
'k': '*1000'
}

text = re.sub(r'(\d+)\s+(кк|к|млн|млрд|k|m|b)\b', r'\1\2', text, flags=re.IGNORECASE)
for short, full in sorted(replacements.items(), key=lambda x: len(x[0]), reverse=True):
text = re.sub(rf'(\d+){short}\b', rf'\1{full}', text, flags=re.IGNORECASE)
new_text = re.sub(r'(\d)\s+(\d)', r'\1\2', new_text)
logger.info(f"After space removal: {new_text}")

text = re.sub(r'(\d)\s+(\d)', r'\1\2', text)

amount_pattern = r'\d+(?:[.,]\d+)?(?:\*\d+)?'
currency_symbols_pattern = '|'.join(map(re.escape, CURRENCY_SYMBOLS.keys()))
currency_abbrev_pattern = '|'.join(map(re.escape, CURRENCY_ABBREVIATIONS.keys()))
Expand All @@ -147,7 +146,7 @@ def parse_amount_and_currency(text: str) -> Tuple[Optional[float], Optional[str]
currency_str = None

for pattern in patterns:
match = re.search(pattern, text, re.IGNORECASE)
match = re.search(pattern, new_text, re.IGNORECASE)
if match:
if len(match.groups()) == 2:
if re.match(amount_pattern, match.group(1)):
Expand All @@ -161,13 +160,14 @@ def parse_amount_and_currency(text: str) -> Tuple[Optional[float], Optional[str]
if not amount_str or not currency_str:
return None, None

amount_str = amount_str.replace(',', '.')
logger.info(f"Matched amount_str: {amount_str}, currency_str: {currency_str}")

try:
if '*' in amount_str:
amount = safe_eval(amount_str)
else:
amount = float(amount_str)
logger.info(f"Parsed amount: {amount}")
logger.info(f"Final parsed amount: {amount}")
except Exception as e:
logger.error(f"Error parsing amount: {e}")
return None, None
Expand Down Expand Up @@ -237,10 +237,10 @@ def format_large_number(number, is_crypto=False):
return formatted.rstrip('0').rstrip('.') if '.' in formatted else formatted

def format_response(response: str, use_quote: bool) -> str:
response = response.strip()
if use_quote:
return f"<blockquote expandable>{response}</blockquote>"
else:
return response
return response

async def delete_conversion_message(callback_query: CallbackQuery):
await callback_query.message.delete()
Expand Down

0 comments on commit ba6f92f

Please sign in to comment.