Add notification for new in-app chat messages (#403)

* Add TG message for new in-app chat messages

* Add emojis and collect phrases
This commit is contained in:
Reckless_Satoshi 2023-03-27 09:37:36 +00:00 committed by GitHub
parent f4ae80c593
commit 399f8102f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 124 additions and 48 deletions

View File

@ -56,6 +56,8 @@ ALTERNATIVE_NAME = 'RoboSats Mainnet'
# Telegram bot token
TELEGRAM_TOKEN = ''
TELEGRAM_BOT_NAME = ''
# Notify new messages in-chat app (fiat exchange step) if at least X minutes has passed since the last chat message.
CHAT_NOTIFICATION_TIMEGAP = 5
# Lightning node open info, url to amboss and 1ML
NETWORK = 'testnet'

View File

@ -9,7 +9,7 @@ from django.utils import timezone
from api.lightning.node import LNNode
from api.models import Currency, LNPayment, MarketTick, OnchainPayment, Order, User
from api.tasks import send_message
from api.tasks import send_notification
from api.utils import validate_onchain_address
FEE = float(config("FEE"))
@ -314,7 +314,7 @@ class Logics:
order.status = Order.Status.EXP
order.expiry_reason = Order.ExpiryReasons.NTAKEN
order.save()
send_message.delay(order.id, "order_expired_untaken")
send_notification.delay(order_id=order.id, message="order_expired_untaken")
return True
elif order.status == Order.Status.TAK:
@ -368,7 +368,7 @@ class Logics:
order.trade_escrow = None
order.payout = None
cls.publish_order(order)
send_message.delay(order.id, "order_published")
send_notification.delay(order_id=order.id, message="order_published")
# Reward maker with part of the taker bond
cls.add_slashed_rewards(taker_bond, order.maker.profile)
return True
@ -399,7 +399,7 @@ class Logics:
order.taker_bond = None
order.trade_escrow = None
cls.publish_order(order)
send_message.delay(order.id, "order_published")
send_notification.delay(order_id=order.id, message="order_published")
# Reward maker with part of the taker bond
cls.add_slashed_rewards(taker_bond, order.maker.profile)
return True
@ -470,7 +470,7 @@ class Logics:
).append(str(order.id))
profile.save()
send_message.delay(order.id, "dispute_opened")
send_notification.delay(order_id=order.id, message="dispute_opened")
return True, None
def dispute_statement(order, user, statement):
@ -815,7 +815,7 @@ class Logics:
order.expires_at = timezone.now() + timedelta(
seconds=order.t_to_expire(Order.Status.CHA)
)
send_message.delay(order.id, "fiat_exchange_starts")
send_notification.delay(order_id=order.id, message="fiat_exchange_starts")
# If the order status is 'Waiting for both'. Move forward to 'waiting for escrow'
elif order.status == Order.Status.WF2:
@ -828,7 +828,9 @@ class Logics:
order.expires_at = timezone.now() + timedelta(
seconds=order.t_to_expire(Order.Status.CHA)
)
send_message.delay(order.id, "fiat_exchange_starts")
send_notification.delay(
order_id=order.id, message="fiat_exchange_starts"
)
else:
order.status = Order.Status.WFE
@ -915,7 +917,9 @@ class Logics:
if cls.return_bond(order.maker_bond):
order.status = Order.Status.UCA
order.save()
send_message.delay(order.id, "public_order_cancelled")
send_notification.delay(
order_id=order.id, message="public_order_cancelled"
)
return True, None
# 2.b) When maker cancels after bond and before taker bond is locked
@ -928,7 +932,9 @@ class Logics:
cls.cancel_bond(order.taker_bond)
order.status = Order.Status.UCA
order.save()
send_message.delay(order.id, "public_order_cancelled")
send_notification.delay(
order_id=order.id, message="public_order_cancelled"
)
return True, None
# 3) When taker cancels before bond
@ -978,7 +984,7 @@ class Logics:
order.payout = None
order.trade_escrow = None
cls.publish_order(order)
send_message.delay(order.id, "order_published")
send_notification.delay(order_id=order.id, message="order_published")
# Reward maker with part of the taker bond
cls.add_slashed_rewards(order.taker_bond, order.maker.profile)
return True, None
@ -1026,7 +1032,7 @@ class Logics:
cls.return_escrow(order)
order.status = Order.Status.CCA
order.save()
send_message.delay(order.id, "collaborative_cancelled")
send_notification.delay(order_id=order.id, message="collaborative_cancelled")
return
@classmethod
@ -1040,7 +1046,7 @@ class Logics:
order.last_satoshis = cls.satoshis_now(order)
order.last_satoshis_time = timezone.now()
order.save()
# send_message.delay(order.id,'order_published') # too spammy
# send_notification.delay(order_id=order.id,'order_published') # too spammy
return
def compute_cltv_expiry_blocks(order, invoice_concept):
@ -1071,7 +1077,7 @@ class Logics:
return True
elif LNNode.validate_hold_invoice_locked(order.maker_bond):
cls.publish_order(order)
send_message.delay(order.id, "order_published")
send_notification.delay(order_id=order.id, message="order_published")
return True
return False
@ -1176,7 +1182,7 @@ class Logics:
MarketTick.log_a_tick(order)
except Exception:
pass
send_message.delay(order.id, "order_taken_confirmed")
send_notification.delay(order_id=order.id, message="order_taken_confirmed")
return True
@classmethod
@ -1272,7 +1278,7 @@ class Logics:
order.expires_at = timezone.now() + timedelta(
seconds=order.t_to_expire(Order.Status.CHA)
)
send_message.delay(order.id, "fiat_exchange_starts")
send_notification.delay(order_id=order.id, message="fiat_exchange_starts")
order.save()
@classmethod
@ -1439,7 +1445,7 @@ class Logics:
order.payout.status = LNPayment.Status.FLIGHT
order.payout.save()
order.save()
send_message.delay(order.id, "trade_successful")
send_notification.delay(order_id=order.id, message="trade_successful")
order.contract_finalization_time = timezone.now()
order.save()
return True
@ -1454,7 +1460,7 @@ class Logics:
order.payout_tx.status = OnchainPayment.Status.QUEUE
order.payout_tx.save()
order.save()
send_message.delay(order.id, "trade_successful")
send_notification.delay(order_id=order.id, message="trade_successful")
order.contract_finalization_time = timezone.now()
order.save()
return True

View File

@ -9,7 +9,7 @@ from django.utils import timezone
from api.lightning.node import LNNode
from api.logics import Logics
from api.models import LNPayment, OnchainPayment, Order
from api.tasks import follow_send_payment, send_message
from api.tasks import follow_send_payment, send_notification
MACAROON = b64decode(config("LND_MACAROON_BASE64"))
@ -228,7 +228,9 @@ class Command(BaseCommand):
# It is a maker bond => Publish order.
if hasattr(lnpayment, "order_made"):
Logics.publish_order(lnpayment.order_made)
send_message.delay(lnpayment.order_made.id, "order_published")
send_notification.delay(
order_id=lnpayment.order_made.id, message="order_published"
)
return
# It is a taker bond => close contract.

View File

@ -5,8 +5,8 @@ from decouple import config
from django.core.management.base import BaseCommand
from django.db import transaction
from api.messages import Telegram
from api.models import Profile
from api.notifications import Telegram
from api.utils import get_session

View File

@ -7,7 +7,7 @@ from api.utils import get_session
class Telegram:
"""Simple telegram messages by requesting to API"""
"""Simple telegram messages using TG's API"""
session = get_session()
site = config("HOST_NAME")
@ -49,9 +49,9 @@ class Telegram:
lang = user.profile.telegram_lang_code
if lang == "es":
text = f"Hola {user.username}, te enviaré notificaciones sobre tus órdenes en RoboSats."
text = f"🔔 Hola {user.username}, te enviaré notificaciones sobre tus órdenes en RoboSats."
else:
text = f"Hey {user.username}, I will send you notifications about your RoboSats orders."
text = f"🔔 Hey {user.username}, I will send you notifications about your RoboSats orders."
self.send_message(user.profile.telegram_chat_id, text)
user.profile.telegram_welcomed = True
user.profile.save()
@ -61,17 +61,17 @@ class Telegram:
if order.maker.profile.telegram_enabled:
lang = order.maker.profile.telegram_lang_code
if lang == "es":
text = f"Hey {order.maker.username} ¡Tu orden con ID {order.id} ha sido tomada por {order.taker.username}!🥳 Visita http://{self.site}/order/{order.id} para continuar."
text = f"Hey {order.maker.username} ¡Tu orden con ID {order.id} ha sido tomada por {order.taker.username}!🥳 Visita http://{self.site}/order/{order.id} para continuar."
else:
text = f"Hey {order.maker.username}, your order was taken by {order.taker.username}!🥳 Visit http://{self.site}/order/{order.id} to proceed with the trade."
text = f"Hey {order.maker.username}, your order was taken by {order.taker.username}!🥳 Visit http://{self.site}/order/{order.id} to proceed with the trade."
self.send_message(order.maker.profile.telegram_chat_id, text)
if order.taker.profile.telegram_enabled:
lang = order.taker.profile.telegram_lang_code
if lang == "es":
text = f"Hey {order.taker.username}, acabas de tomar la orden con ID {order.id}."
text = f"Hey {order.taker.username}, acabas de tomar la orden con ID {order.id}."
else:
text = f"Hey {order.taker.username}, you just took the order with ID {order.id}."
text = f"Hey {order.taker.username}, you just took the order with ID {order.id}."
self.send_message(order.taker.profile.telegram_chat_id, text)
return
@ -81,9 +81,9 @@ class Telegram:
if user.profile.telegram_enabled:
lang = user.profile.telegram_lang_code
if lang == "es":
text = f"Hey {user.username}, el depósito de garantía y el recibo del comprador han sido recibidos. Es hora de enviar el dinero fiat. Visita http://{self.site}/order/{order.id} para hablar con tu contraparte."
text = f"Hey {user.username}, el depósito de garantía y el recibo del comprador han sido recibidos. Es hora de enviar el dinero fiat. Visita http://{self.site}/order/{order.id} para hablar con tu contraparte."
else:
text = f"Hey {user.username}, the escrow and invoice have been submitted. The fiat exchange starts now via the platform chat. Visit http://{self.site}/order/{order.id} to talk with your counterpart."
text = f"Hey {user.username}, the escrow and invoice have been submitted. The fiat exchange starts now via the platform chat. Visit http://{self.site}/order/{order.id} to talk with your counterpart."
self.send_message(user.profile.telegram_chat_id, text)
return
@ -91,9 +91,9 @@ class Telegram:
if order.maker.profile.telegram_enabled:
lang = order.maker.profile.telegram_lang_code
if lang == "es":
text = f"Hey {order.maker.username}, tu orden con ID {order.id} ha expirado sin ser tomada por ningún robot. Visita http://{self.site}/order/{order.id} para renovarla."
text = f"😪 Hey {order.maker.username}, tu orden con ID {order.id} ha expirado sin ser tomada por ningún robot. Visita http://{self.site}/order/{order.id} para renovarla."
else:
text = f"Hey {order.maker.username}, your order with ID {order.id} has expired without a taker. Visit http://{self.site}/order/{order.id} to renew it."
text = f"😪 Hey {order.maker.username}, your order with ID {order.id} has expired without a taker. Visit http://{self.site}/order/{order.id} to renew it."
self.send_message(order.maker.profile.telegram_chat_id, text)
return
@ -102,9 +102,9 @@ class Telegram:
if user.profile.telegram_enabled:
lang = user.profile.telegram_lang_code
if lang == "es":
text = f"¡Tu orden con ID {order.id} ha finalizado exitosamente!⚡ Únete a nosotros en @robosats_es y ayúdanos a mejorar."
text = f"🥳 ¡Tu orden con ID {order.id} ha finalizado exitosamente!⚡ Únete a nosotros en @robosats_es y ayúdanos a mejorar."
else:
text = f"Your order with ID {order.id} has finished successfully!⚡ Join us @robosats and help us improve."
text = f"🥳 Your order with ID {order.id} has finished successfully!⚡ Join us @robosats and help us improve."
self.send_message(user.profile.telegram_chat_id, text)
return
@ -112,9 +112,9 @@ class Telegram:
if order.maker.profile.telegram_enabled:
lang = order.maker.profile.telegram_lang_code
if lang == "es":
text = f"Hey {order.maker.username}, has cancelado tu orden pública con ID {order.id}."
text = f"Hey {order.maker.username}, has cancelado tu orden pública con ID {order.id}."
else:
text = f"Hey {order.maker.username}, you have cancelled your public order with ID {order.id}."
text = f"Hey {order.maker.username}, you have cancelled your public order with ID {order.id}."
self.send_message(order.maker.profile.telegram_chat_id, text)
return
@ -123,9 +123,9 @@ class Telegram:
if user.profile.telegram_enabled:
lang = user.profile.telegram_lang_code
if lang == "es":
text = f"Hey {user.username}, tu orden con ID {str(order.id)} fue cancelada colaborativamente."
text = f"Hey {user.username}, tu orden con ID {str(order.id)} fue cancelada colaborativamente."
else:
text = f"Hey {user.username}, your order with ID {str(order.id)} has been collaboratively cancelled."
text = f"Hey {user.username}, your order with ID {str(order.id)} has been collaboratively cancelled."
self.send_message(user.profile.telegram_chat_id, text)
return
@ -134,9 +134,9 @@ class Telegram:
if user.profile.telegram_enabled:
lang = user.profile.telegram_lang_code
if lang == "es":
text = f"Hey {user.username}, la orden con ID {str(order.id)} ha entrado en disputa."
text = f"⚖️ Hey {user.username}, la orden con ID {str(order.id)} ha entrado en disputa."
else:
text = f"Hey {user.username}, a dispute has been opened on your order with ID {str(order.id)}."
text = f"⚖️ Hey {user.username}, a dispute has been opened on your order with ID {str(order.id)}."
self.send_message(user.profile.telegram_chat_id, text)
return
@ -149,8 +149,39 @@ class Telegram:
return
order = queryset.last()
if lang == "es":
text = f"Hey {order.maker.username}, tu orden con ID {str(order.id)} es pública en el libro de ordenes."
text = f"Hey {order.maker.username}, tu orden con ID {str(order.id)} es pública en el libro de ordenes."
else:
text = f"Hey {order.maker.username}, your order with ID {str(order.id)} is public in the order book."
text = f"Hey {order.maker.username}, your order with ID {str(order.id)} is public in the order book."
self.send_message(order.maker.profile.telegram_chat_id, text)
return
def new_chat_message(self, order, chat_message):
"""
Sends a TG notification for a new in-app chat message if
the last chat was at least CHAT_NOTIFICATION_TIMEGAP minutes ago.
"""
from datetime import timedelta
from django.utils import timezone
from chat.models import Message
TIMEGAP = config("CHAT_NOTIFICATION_TIMEGAP", cast=int, default=5)
if chat_message.index > 1:
previous_message = Message.objects.get(
chatroom=chat_message.chatroom, index=(chat_message.index - 1)
)
notification_reason = f"(You receive this notification only because more than {TIMEGAP} minutes have passed since the last in-chat message)"
if previous_message.created_at > timezone.now() - timedelta(
minutes=TIMEGAP
):
return
else:
notification_reason = f"(You receive this notification because this was the first in-chat message. You will only be notified again if there is a gap bigger than {TIMEGAP} minutes between messages)"
user = chat_message.receiver
if user.profile.telegram_enabled:
text = f"💬 Hey {user.username}, a new chat message in-app was sent to you by {chat_message.sender.username} for order ID {str(order.id)}. {notification_reason}"
self.send_message(user.profile.telegram_chat_id, text)
return

View File

@ -313,19 +313,26 @@ def cache_market():
return results
@shared_task(name="send_message", ignore_result=True)
def send_message(order_id, message):
@shared_task(name="send_notification", ignore_result=True)
def send_notification(order_id=None, chat_message_id=None, message=None):
from api.models import Order
if order_id:
from api.models import Order
order = Order.objects.get(id=order_id)
elif chat_message_id:
from chat.models import Message
chat_message = Message.objects.get(id=chat_message_id)
order = chat_message.order
order = Order.objects.get(id=order_id)
taker_enabled = (
False if order.taker is None else order.taker.profile.telegram_enabled
)
if not (order.maker.profile.telegram_enabled or taker_enabled):
return
from api.messages import Telegram
from api.notifications import Telegram
telegram = Telegram()
@ -359,4 +366,7 @@ def send_message(order_id, message):
elif message == "collaborative_cancelled":
telegram.collaborative_cancelled(order)
elif message == "new_chat_message":
telegram.new_chat_message(order, chat_message)
return

View File

@ -19,8 +19,8 @@ from robohash import Robohash
from scipy.stats import entropy
from api.logics import Logics
from api.messages import Telegram
from api.models import Currency, LNPayment, MarketTick, OnchainPayment, Order, Profile
from api.notifications import Telegram
from api.oas_schemas import (
BookViewSchema,
HistoricalViewSchema,

View File

@ -4,6 +4,7 @@ from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer
from api.models import Order
from api.tasks import send_notification
from chat.models import ChatRoom, Message
@ -78,6 +79,9 @@ class ChatRoomConsumer(AsyncWebsocketConsumer):
receiver=receiver,
PGP_message=PGP_message,
)
# send Telegram notification for new message (if conditions apply)
send_notification.delay(chat_message_id=msg_obj.id, message="new_chat_message")
return msg_obj
@database_sync_to_async

View File

@ -7,6 +7,7 @@ from rest_framework import status, viewsets
from rest_framework.response import Response
from api.models import Order, User
from api.tasks import send_notification
from chat.models import ChatRoom, Message
from chat.serializers import ChatSerializer, PostMessageSerializer
@ -160,6 +161,11 @@ class ChatView(viewsets.ViewSet):
receiver=receiver,
)
# send Telegram notification for new message (if conditions apply)
send_notification.delay(
chat_message_id=new_message.id, message="new_chat_message"
)
# Send websocket message
if chatroom.maker == request.user:
peer_connected = chatroom.taker_connected

View File

@ -77,7 +77,7 @@ const ChatHeader: React.FC<Props> = ({ connected, peerConnected, turtleMode, set
>
<Typography align='center' variant='caption' sx={{ color: connectedTextColor }}>
{t('Peer') + ': '}
{connected ? (peerConnected ? t('connected') : t('disconnected')) : '...waiting'}
{connected ? (peerConnected ? t('connected') : t('disconnected')) : t('...waiting')}
</Typography>
</Paper>
</Grid>

View File

@ -423,6 +423,7 @@
"disconnected": "desconnectat",
"Activate slow mode (use it when the connection is slow)": "Activar mode lent (utilitza'l quan la connexió sigui lenta)",
"Peer": "Ell",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Verifica la teva privacitat",

View File

@ -423,6 +423,7 @@
"disconnected": "odpojen",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "Protistrana",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Ověř svou ochranu soukromí",

View File

@ -423,6 +423,7 @@
"disconnected": "getrennt",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "Partner",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Überprüfe deine Privatsphäre",

View File

@ -423,6 +423,7 @@
"disconnected": "disconnected",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "Peer",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Verify your privacy",

View File

@ -423,6 +423,7 @@
"disconnected": "desconectado",
"Activate slow mode (use it when the connection is slow)": "Activar modo lento (Úsalo cuando tu conexión sea inestable)",
"Peer": "Él",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Verifica tu privacidad",

View File

@ -423,6 +423,7 @@
"disconnected": "deskonektatuta",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "Bera",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Zure pribatasuna egiaztatu",

View File

@ -423,6 +423,7 @@
"disconnected": "déconnecté",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "Pair",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Verify your privacy",

View File

@ -423,6 +423,7 @@
"disconnected": "disconnesso",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "Pari",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Verificando la tua privacy",

View File

@ -423,6 +423,7 @@
"disconnected": "niepowiązany",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "Par",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Verify your privacy",

View File

@ -423,6 +423,7 @@
"disconnected": "desconectado",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "Par",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Verifique sua privacidade",

View File

@ -423,6 +423,7 @@
"disconnected": "отключен",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "Партнёр",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Проверьте свою конфиденциальность",

View File

@ -423,6 +423,7 @@
"disconnected": "ej ansluten",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "Peer",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "Verifiera din integritet",

View File

@ -423,6 +423,7 @@
"disconnected": "ตัดการเชื่อมต่อแล้ว",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "คู่ค้า",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "ตรวจสอบความเป็นส่วนตัวของคุณ",

View File

@ -423,6 +423,7 @@
"disconnected": "离线",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "对等方",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "验证你的隐私",

View File

@ -423,6 +423,7 @@
"disconnected": "離線",
"Activate slow mode (use it when the connection is slow)": "Activate slow mode (use it when the connection is slow)",
"Peer": "對等方",
"...waiting": "...waiting",
"#42": "Phrases in components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx",
"#43": "Phrases in components/TradeBox/EncryptedChat/ChatBottom/index.tsx",
"Verify your privacy": "驗證你的隱私",