I'm writing my first telegram bot with telepot and telethon
my main code is:
import sys
import asyncio
import random
import telepot
import telepot.aio
from telepot.aio.loop import MessageLoop
from telepot.namedtuple import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove, ForceReply
from telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton
from telepot.namedtuple import InlineQueryResultArticle, InlineQueryResultPhoto, InputTextMessageContent
async def on_chat_message(msg):
global listenFromKeyboardUsername, listenFromKeyboardPassword, listenFromKeyboardLinkGroup
content_type, chat_type, chat_id = telepot.glance(msg)
chat_id = str(chat_id)
if content_type == 'text':
name = msg["from"]["first_name"]
txt = msg['text']
# stuff..
elif userExistsInDb and userData['listenFromKeyboardLinkGroup'] and chat_id == doc.id:
group = telegramGetMessages.checkGroup(txt)
print(group)
TOKEN = "*******"
bot = telepot.aio.Bot(TOKEN)
answerer = telepot.aio.helper.Answerer(bot)
loop = asyncio.get_event_loop()
loop.create_task(MessageLoop(bot, {'chat': on_chat_message,
'callback_query': on_callback_query}).run_forever())
print('Listening ...')
loop.run_forever()
from the code above I call the checkGroup function:
def checkGroup(hash):
initClient()
global result
hash = hash.replace('https://t.me/joinchat/', '')
with TelegramClient(name, api_id, api_hash) as client:
result = client(functions.messages.CheckChatInviteRequest(hash=hash))
if isinstance(result, ChatInvite):
print('You are not inside the group')
with TelegramClient(name, api_id, api_hash) as client:
client(functions.messages.ImportChatInviteRequest(hash=hash))
result = client(functions.messages.CheckChatInviteRequest(hash=hash))
return result
where I'm getting this error:
RuntimeError: You must use "async with" if the event loop is running (i.e. you are inside an "async def")
then I edit the checkGroup function with async def checkGroup(hash): ..
but now I'm geting this error and I don't know what to do:
Task exception was never retrieved
future: <Task finished coro=<Router.route() done, defined at /home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/telepot/aio/helper.py:213> exception=NotFound('No document to update: projects/telegram-bot-4ee9f/databases/(default)/documents/users/585089661/data/groups',)>
Traceback (most recent call last):
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/google/api_core/grpc_helpers.py", line 57, in error_remapped_callable
return callable_(*args, **kwargs)
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/grpc/_channel.py", line 549, in __call__
return _end_unary_response_blocking(state, call, False, None)
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/grpc/_channel.py", line 466, in _end_unary_response_blocking
raise _Rendezvous(state, None, None, deadline)
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with:
status = StatusCode.NOT_FOUND
details = "No document to update: projects/telegram-bot-4ee9f/databases/(default)/documents/users/585089661/data/groups"
debug_error_string = "{"created":"#1552727386.760400590","description":"Error received from peer","file":"src/core/lib/surface/call.cc","file_line":1039,"grpc_message":"No document to update: projects/telegram-bot-4ee9f/databases/(default)/documents/users/585089661/data/groups","grpc_status":5}"
>
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/telepot/aio/helper.py", line 244, in route
return await _invoke(fn, msg, *args, **kwargs)
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/telepot/aio/helper.py", line 16, in _invoke
return await fn(*args, **kwargs)
File "/home/ale/PycharmProjects/newTelegramBot/chatAsync.py", line 119, in on_chat_message
database.updateUserData(chat_id, 'groups', 'nameGroup', txt)
File "/home/ale/PycharmProjects/newTelegramBot/database.py", line 38, in updateUserData
field: key,
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/google/cloud/firestore_v1beta1/document.py", line 371, in update
write_results = batch.commit()
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/google/cloud/firestore_v1beta1/batch.py", line 148, in commit
metadata=self._client._rpc_metadata,
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/google/cloud/firestore_v1beta1/gapic/firestore_client.py", line 946, in commit
request, retry=retry, timeout=timeout, metadata=metadata
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/google/api_core/gapic_v1/method.py", line 143, in __call__
return wrapped_func(*args, **kwargs)
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/google/api_core/retry.py", line 270, in retry_wrapped_func
on_error=on_error,
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/google/api_core/retry.py", line 179, in retry_target
return target()
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/google/api_core/timeout.py", line 214, in func_with_timeout
return func(*args, **kwargs)
File "/home/ale/PycharmProjects/newTelegramBot/venv/lib/python3.6/site-packages/google/api_core/grpc_helpers.py", line 59, in error_remapped_callable
six.raise_from(exceptions.from_grpc_error(exc), exc)
File "<string>", line 3, in raise_from
google.api_core.exceptions.NotFound: 404 No document to update: projects/telegram-bot-4ee9f/databases/(default)/documents/users/585089661/data/groups
/usr/lib/python3.6/asyncio/base_events.py:1441: RuntimeWarning: coroutine 'checkGroup' was never awaited
handle = None # Needed to break cycles when an exception occurs.
I'm reading around, and maybe for this problem it's better to use the delegatoBot, but I'm not really sure because I can't find great examples!
It wold be wonderfull recive a reply, If you need anything just ask!
Thankyou
Related
async def dumpData(session, url, data): r = await session.get(headers=headers,url=url) await r.html.arender(sleep=5) html_content = r.html.html soup = BeautifulSoup(html_content, 'html.parser')
This is a part of my code and I am trying get data from a website and but "r.html.arender(sleep=5)" never waits. and after a few minutes it raise this errors;
"Traceback (most recent call last): File "/Users/scoskun/Desktop/webscraping/2test.py", line 86, in <module> results = asyncio.run(main(["https://www.example.com"])) File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete return future.result() File "/Users/scoskun/Desktop/webscraping/2test.py", line 83, in main return await asyncio.gather(*tasks) File "/Users/scoskun/Desktop/webscraping/2test.py", line 54, in dumpData await r.html.arender(sleep=5) File "/Users/scoskun/Library/Python/3.9/lib/python/site-packages/requests_html.py", line 615, in arender self.browser = await self.session.browser File "/Users/scoskun/Library/Python/3.9/lib/python/site-packages/requests_html.py", line 714, in browser self._browser = await pyppeteer.launch(ignoreHTTPSErrors=not(self.verify), headless=True, args=self.__browser_args) File "/Users/scoskun/Library/Python/3.9/lib/python/site-packages/pyppeteer/launcher.py", line 307, in launch return await Launcher(options, **kwargs).launch() File "/Users/scoskun/Library/Python/3.9/lib/python/site-packages/pyppeteer/launcher.py", line 168, in launch self.browserWSEndpoint = get_ws_endpoint(self.url) File "/Users/scoskun/Library/Python/3.9/lib/python/site-packages/pyppeteer/launcher.py", line 227, in get_ws_endpoint raise BrowserError('Browser closed unexpectedly:\n') pyppeteer.errors.BrowserError: Browser closed unexpectedly: "
I have tried to add more minutes to render(sleep) but still not working.
I developed an API with FastAPI and when I run it in my conda Ubuntu enviroment, and try any function all runs perfectly. But, when I run it in my conda Windows enviroment the API runs okey but when I try the functoin, I get the internal server error message as output and in the terminal i can see the following error described below. Note, the code is the same in both enviroments
Also, the conexion in jupyter notebook(in the conda windows enviroment) to the node works fine as well as any function I run.
This is the conexion via jupyter, thath works fine in both enviroments:
rpc_user = os.getenv("u1")
rpc_password = os.getenv("key2")
rpc_host = os.getenv("host")
rpc_client = AuthServiceProxy(f"http://{rpc_user}:{rpc_password}#{rpc_host}", timeout=120)
block_count = rpc_client.getblockcount()
print("---------------------------------------------------------------")
print("Block Count:", block_count)
print("---------------------------------------------------------------\n")
output:
---------------------------------------------------------------
Block Count: 773863
---------------------------------------------------------------
This is the code for the connection in the API that it is in a directory named blockchain_data :
import os
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
import json
client = os.getenv("u1")
key = os.getenv("key2")
host= os.getenv("host")
rpc_client = AuthServiceProxy(f"http://{client}:{key}#{host}", timeout=120)
This is the router for getblockcount, that works fine in my ubuntu enviroment but not in the windows.
from fastapi import APIRouter
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
from blockchain_data.node import rpc_client
router = APIRouter()
#router.get("/get/block/count")
def get_block_count():
block_count = rpc_client.getblockcount()
return {"Last block":block_count}
And the main:
from fastapi import FastAPI
from routers import routers
app = FastAPI()
app.include_router(routers.router)
#app.get("/")
def inicio():
return{
"message": "welcome"
}
ERROR:
←[1mGET /get/block/count HTTP/1.1←[0m" ←[91m500 Internal Server Error←[0m
←[31mERROR←[0m: Exception in ASGI application
Traceback (most recent call last):
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 407, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\fastapi\applications.py", line 270, in __call__
await super().__call__(scope, receive, send)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\starlette\applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\starlette\middleware\errors.py", line 184, in __call__
raise exc
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\starlette\middleware\errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\starlette\middleware\exceptions.py", line 79, in __call__
raise exc
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\starlette\middleware\exceptions.py", line 68, in __call__
await self.app(scope, receive, sender)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__
raise e
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\starlette\routing.py", line 706, in __call__
await route.handle(scope, receive, send)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\starlette\routing.py", line 276, in handle
await self.app(scope, receive, send)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\starlette\routing.py", line 66, in app
response = await func(request)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\fastapi\routing.py", line 237, in app
raw_response = await run_endpoint_function(
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\fastapi\routing.py", line 165, in run_endpoint_function
return await run_in_threadpool(dependant.call, **values)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\starlette\concurrency.py", line 41, in run_in_threadpool
return await anyio.to_thread.run_sync(func, *args)
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\anyio\to_thread.py", line 31, in run_sync
return await get_asynclib().run_sync_in_worker_thread(
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\anyio\_backends\_asyncio.py", line 937, in run_sync_in_worker_thread
return await future
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\anyio\_backends\_asyncio.py", line 867, in run
result = context.run(func, *args)
File ".\routers\routers.py", line 17, in get_block_count
block_count = rpc_client.getblockcount()
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\bitcoinrpc\authproxy.py", line 139, in __call__
response = self._get_response()
File "C:\Users\grupo\miniconda3\envs\entorno1\lib\site-packages\bitcoinrpc\authproxy.py", line 186, in _get_response
raise JSONRPCException({
bitcoinrpc.authproxy.JSONRPCException: -342: non-JSON HTTP response with '401 Unauthorized' from server
I tried to run the conexion with the node in jupter and works fine, it something related to FastAPI or uvicorn
I need to write this HTTP request.
I was able to get the token (from another HTTP request) and I saved on in a variable name "Token"
Can you please help me write this HTTP request in python?
I am getting 404 and I am pretty sure the syntax is wrong.
Attaching a screenshot from Microsoft documentation.
the new error message:
Traceback (most recent call last):
File "/Users/talcohen/opt/anaconda3/lib/python3.9/site-packages/requests/models.py", line 972, in json
return complexjson.loads(self.text, **kwargs)
File "/Users/talcohen/opt/anaconda3/lib/python3.9/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "/Users/talcohen/opt/anaconda3/lib/python3.9/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/Users/talcohen/opt/anaconda3/lib/python3.9/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/talcohen/Documents/ddd/PowerBI_REST_API/CreateProfile.py", line 15, in <module>
data = requests.post(api_url, json=payload, headers=headers).json()
File "/Users/talcohen/opt/anaconda3/lib/python3.9/site-packages/requests/models.py", line 976, in json
raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
(base) talcohen#Tals-Mac-mini PowerBI_REST_API %
Looking at the API you should probably do:
import requests
token = "<YOUR TOKEN>"
api_url = "https://api.powerbi.com/v1.0/myorg/profiles"
headers = {"Authorization": f"Bearer {token}"}
payload = {"displayName": "My First Profile"}
data = requests.post(api_url, json=payload, headers=headers).json()
print(data)
I'm facing an issue I'm having a hard time to identify.
I made a Database context system to wrap requests inside with that creates a connection to Mysql. Here's the full code :
custom/database/database.py
# -*- coding:utf-8 -*-
from sqlalchemy import exc, event
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession as SQLAlchemyAsyncSession
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.pool import Pool, QueuePool # NullPool
from sqlalchemy.exc import OperationalError
from contextvars import ContextVar
from sanic import Sanic
class EngineNotInitialisedError(Exception):
pass
class DBSessionContext:
def __init__(self, read_session: Session, write_session: Session, commit_on_exit: bool = True) -> None:
self.read_session = read_session
self.write_session = write_session
self.commit_on_exit = commit_on_exit
self.token = None
self._read = None
self._write = None
def _disable_flush(self, *args, **kwargs):
raise NotImplementedError('Unable to flush a read-only session.')
async def close(self, exc_type=None, exc_value=None, traceback=None):
if self._write:
if exc_value and getattr(exc_value, 'status_code', 500) > 300:
await self._write.rollback()
else:
await self._write.commit()
try:
await self._write.close()
except OperationalError as e:
if e.orig.args[0] != 2013: # Lost connection to MySQL server during query
raise e
if self._read:
try:
await self._read.close()
except OperationalError as e:
if e.orig.args[0] != 2013: # Lost connection to MySQL server during query
raise e
def set_token(self, token):
self.token = token
#property
def read(self) -> Session:
if not self._read:
self._read = self.read_session()
self._read.flush = self._disable_flush
return self._read
#property
def write(self) -> Session:
if not self._write:
self._write = self.write_session()
return self._write
class AsyncSession(SQLAlchemyAsyncSession):
async def execute(self, statement, **parameters):
return await super().execute(statement, parameters)
async def first(self, statement, **parameters):
executed = await self.execute(statement, **parameters)
return executed.first()
async def all(self, statement, **parameters):
executed = await self.execute(statement, **parameters)
return executed.all()
class DBSession:
def __init__(self):
self.app = None
self.read_engine = None
self.read_session = None
self.write_engine = None
self.write_session = None
self._session = None
self.context = ContextVar("context", default=None)
self.commit_on_exit = True
def init_app(self, app: Sanic) -> None:
self.app = app
self.commit_on_exit = self.app.config.get('DATABASE_COMMIT_ON_EXIT', cast=bool, default=True)
engine_args = {
'echo': self.app.config.get('DATABASE_ECHO', cast=bool, default=False),
'echo_pool': self.app.config.get('DATABASE_ECHO_POOL', cast=bool, default=False),
'poolclass': QueuePool, # will be used to create a connection pool instance using the connection parameters given in the URL
# if pool_class is not NullPool:
# if True will enable the connection pool “pre-ping” feature that tests connections for liveness upon each checkout
'pool_pre_ping': self.app.config.get('DATABASE_POOL_PRE_PING', cast=bool, default=True),
# the number of connections to allow in connection pool “overflow”
'max_overflow': self.app.config.get('DATABASE_MAX_OVERFLOW', cast=int, default=10),
# the number of connections to keep open inside the connection pool
'pool_size': self.app.config.get('DATABASE_POOL_SIZE', cast=int, default=100),
# this setting causes the pool to recycle connections after the given number of seconds has passed
'pool_recycle': self.app.config.get('DATABASE_POOL_RECYCLE', cast=int, default=3600),
# number of seconds to wait before giving up on getting a connection from the pool
'pool_timeout': self.app.config.get('DATABASE_POOL_TIMEOUT', cast=int, default=5),
}
self.read_engine = create_async_engine(
self.app.config.get('DATABASE_READ_URL'),
connect_args={
'connect_timeout': self.app.config.get('DATABASE_CONNECT_TIMEOUT', cast=int, default=3)
},
**engine_args
)
# #see https://writeonly.wordpress.com/2009/07/16/simple-read-only-sqlalchemy-sessions/
self.read_session = sessionmaker(
bind=self.read_engine,
expire_on_commit=False,
class_=AsyncSession,
autoflush=False,
autocommit=False
)
self.write_engine = create_async_engine(
self.app.config.get('DATABASE_WRITE_URL'),
connect_args={
'connect_timeout': self.app.config.get('DATABASE_CONNECT_TIMEOUT', cast=int, default=3)
},
**engine_args
)
self.write_session = sessionmaker(
bind=self.write_engine,
expire_on_commit=False,
class_=AsyncSession,
autoflush=True
)
async def __aenter__(self):
session_ctx = DBSessionContext(self.read_session, self.write_session, self.commit_on_exit)
session_ctx.set_token(self.context.set(session_ctx))
return session_ctx
async def __aexit__(self, exc_type, exc_value, traceback):
session_ctx = self.context.get()
await session_ctx.close(exc_type, exc_value, traceback)
self.context.reset(session_ctx.token)
#property
def read(self) -> Session:
return self.context.get().read
#property
def write(self) -> Session:
return self.context.get().write
#event.listens_for(Pool, "checkout")
def check_connection(dbapi_con, con_record, con_proxy):
'''Listener for Pool checkout events that pings every connection before using.
Implements pessimistic disconnect handling strategy. See also:
http://docs.sqlalchemy.org/en/rel_0_8/core/pooling.html#disconnect-handling-pessimistic'''
cursor = dbapi_con.cursor()
try:
cursor.execute("SELECT 1")
except exc.OperationalError as ex:
if ex.args[0] in (2006, # MySQL server has gone away
2013, # Lost connection to MySQL server during query
2055): # Lost connection to MySQL server at '%s', system error: %d
raise exc.DisconnectionError() # caught by pool, which will retry with a new connection
else:
raise
cursor.close()
db = DBSession()
Using it is quite simple, I do the following. In the router, I made a wrapper that calls the handler with the db initiated:
custom/route.py
class Route:
async def __call__(self, request: Request, **kwargs):
async with db:
response = await self.handler(*args)
# process the response, such as chaning a str to a text response, etc
return response
Unfortunately, I noticed that I have a lot of
(2013, 'Lost connection to MySQL server during query')
And I don't know how or why this happens. This happens to relatively small queries (that contains "LIMIT 1" with indexed columns that should be fast)
Here's the full stack trace:
[2022-05-19 09:35:25 +0000] [92185] [ERROR] Exception occurred while handling uri: 'https://api.pdfshift.io/redacted'
Traceback (most recent call last):
File "asyncmy/connection.pyx", line 610, in asyncmy.connection.Connection._read_bytes
data = await self._reader.readexactly(num_bytes)
File "/usr/lib/python3.9/asyncio/streams.py", line 721, in readexactly
raise exceptions.IncompleteReadError(incomplete, n)
asyncio.exceptions.IncompleteReadError: 0 bytes read on a total of 4 expected bytes
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1802, in _execute_context
self.dialect.do_execute(
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 732, in do_execute
cursor.execute(statement, parameters)
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/dialects/mysql/asyncmy.py", line 92, in execute
return self.await_(self._execute_async(operation, parameters))
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 76, in await_only
return current.driver.switch(awaitable)
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 129, in greenlet_spawn
value = await result
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/dialects/mysql/asyncmy.py", line 104, in _execute_async
result = await self._cursor.execute(operation, parameters)
File "asyncmy/cursors.pyx", line 180, in execute
result = await self._query(query)
File "asyncmy/cursors.pyx", line 365, in _query
await conn.query(q)
File "asyncmy/connection.pyx", line 455, in query
await self._read_query_result(unbuffered=unbuffered)
File "asyncmy/connection.pyx", line 636, in _read_query_result
await result.read()
File "asyncmy/connection.pyx", line 1023, in read
first_packet = await self.connection.read_packet()
File "asyncmy/connection.pyx", line 578, in read_packet
packet_header = await self._read_bytes(4)
File "asyncmy/connection.pyx", line 618, in _read_bytes
raise errors.OperationalError(CR_SERVER_LOST, msg) from e
asyncmy.errors.OperationalError: (2013, 'Lost connection to MySQL server during query')
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "handle_request", line 83, in handle_request
)
File "/var/www/project/www/custom/route.py", line 162, in __call__
response = await response
File "/var/www/project/www/apps/webhooks/views.py", line 104, in stripe
await account.reset_usage()
File "/var/www/project/www/apps/accounts/models.py", line 133, in reset_usage
while await db.read.first(query, uuid=self.uuid):
File "/var/www/project/www/custom/database/database.py", line 73, in first
executed = await self.execute(statement, **parameters)
File "/var/www/project/www/custom/database/database.py", line 70, in execute
return await super().execute(statement, parameters)
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/ext/asyncio/session.py", line 211, in execute
return await greenlet_spawn(
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 134, in greenlet_spawn
result = context.throw(*sys.exc_info())
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/orm/session.py", line 1692, in execute
result = conn._execute_20(statement, params or {}, execution_options)
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1614, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/sql/elements.py", line 325, in _execute_on_connection
return connection._execute_clauseelement(
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1481, in _execute_clauseelement
ret = self._execute_context(
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1845, in _execute_context
self._handle_dbapi_exception(
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2026, in _handle_dbapi_exception
util.raise_(
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1802, in _execute_context
self.dialect.do_execute(
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 732, in do_execute
cursor.execute(statement, parameters)
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/dialects/mysql/asyncmy.py", line 92, in execute
return self.await_(self._execute_async(operation, parameters))
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 76, in await_only
return current.driver.switch(awaitable)
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 129, in greenlet_spawn
value = await result
File "/var/www/project/env/lib/python3.9/site-packages/sqlalchemy/dialects/mysql/asyncmy.py", line 104, in _execute_async
result = await self._cursor.execute(operation, parameters)
File "asyncmy/cursors.pyx", line 180, in execute
result = await self._query(query)
File "asyncmy/cursors.pyx", line 365, in _query
await conn.query(q)
File "asyncmy/connection.pyx", line 455, in query
await self._read_query_result(unbuffered=unbuffered)
File "asyncmy/connection.pyx", line 636, in _read_query_result
await result.read()
File "asyncmy/connection.pyx", line 1023, in read
first_packet = await self.connection.read_packet()
File "asyncmy/connection.pyx", line 578, in read_packet
packet_header = await self._read_bytes(4)
File "asyncmy/connection.pyx", line 618, in _read_bytes
raise errors.OperationalError(CR_SERVER_LOST, msg) from e
sqlalchemy.exc.OperationalError: (asyncmy.errors.OperationalError) (2013, 'Lost connection to MySQL server during query')
[SQL: SELECT id FROM conversions WHERE [redacted] LIMIT 1]
[parameters: ('redacted',)]
(Background on this error at: https://sqlalche.me/e/14/e3q8)
When connecting to the database, here's the parameter I provide:
DATABASE_POOL_PRE_PING = True
DATABASE_MAX_OVERFLOW = 10
DATABASE_POOL_SIZE = 100
DATABASE_POOL_RECYCLE = 3600
DATABASE_POOL_TIMEOUT = 5
DATABASE_CONNECT_TIMEOUT = 3
(If you need details from the MySQL server side, let me know which command to run and I'll add the output here).
My assumption is that somehow, the connection is not properly closed when exiting the async with db part, so when another requests comes in, the same connection is used, but ultimately, MySQL kills it, causing the above error Lost connection to MySQL server during query
Further details :
The error is the same, but the queries changes, showing that the error is not from a specific part of the code, but related to the connection
I was able to catch this issue when sending a webhook event from Stripe. The error returned by Stripe is "Expired". Which seems to indicate that before being stopped, the connection hangs (probably waiting on the SQL query to finish)
This doesn't happen everytime : I was able to run some webhooks successfully, and other not, for the same event (Stripe), so again, it doesn't seems to be an error with the code related to handling the request (but maybe on how the DB is managed)
Thank you for your help !
I am trying to host my telegram bot for a multiplayer game on GAE and web hook is used here. This is how my databasing part is like:
class Game(ndb.Model):
chat_id = ndb.IntegerProperty(required = True)
mission_num = ndb.IntegerProperty(default =1)
round_num = ndb.IntegerProperty(default =1)
class Player(ndb.Model):
user_id = ndb.IntegerProperty(required=True)
player_role = ndb.StringProperty (
choices = ['spy','resistance'])
The part of code under web hook handler:
if text.startswith('/'):
if text == '/start':
reply('Bot enabled')
setEnabled(chat_id, True)
elif text == '/stop':
reply('Bot disabled')
setEnabled(chat_id, False)
elif text == '/newgame':
if chat_type == 'group':
existing_game = Game.query (Game.chat_id == chat_id).get()
if existing_game:
reply ("game is alr intitiated liao")
else:
##create a new game here
#still stuck here
##========================##
#reply("keep replying this line")
##========================##
new_game = Game (
chat_id = chat_id,
id = chat_id
)
curr_game_key = new_game.put()
new_player = Player (
parent = curr_game_key,
user_id = fr_user_id,
id = fr_user_id)
new_player.put()
reply("waiting for more friends to join")
else:
reply('game must be conducted within a group chat! jio more friends!')
else:
reply('What command?')
else:
if getEnabled(chat_id):
reply('I got your message! (but I do not know how to answer)')
else:
logging.info('not enabled for chat_id {}'.format(chat_id))
The problem is that when I send '/newgame' in a group chat, nothing is sent back to me. If I uncomment the following line my bot keeps sending me "keep replying this line" like crazy.:
#reply("keep replying this line")
The reply function:
def reply(msg=None, img=None):
if msg:
resp = urllib2.urlopen(BASE_URL + 'sendMessage', urllib.urlencode({
'chat_id': str(chat_id),
'text': msg.encode('utf-8'),
'disable_web_page_preview': 'true',
'reply_to_message_id': str(message_id),
})).read()
elif img:
resp = multipart.post_multipart(BASE_URL + 'sendPhoto', [
('chat_id', str(chat_id)),
('reply_to_message_id', str(message_id)),
], [
('photo', 'image.jpg', img),
])
else:
logging.error('no msg or img specified')
resp = None
logging.info('send response:')
logging.info(resp)
The error:
Internal Server Error
The server has either erred or is incapable of performing the requested operation.
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~orbitaltest2/1.393734187774164753/main.py", line 66, in get
self.response.write(json.dumps(json.load(urllib2.urlopen(BASE_URL + 'getUpdates'))))
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 127, in urlopen
return _opener.open(url, data, timeout)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 410, in open
response = meth(req, response)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 523, in http_response
'http', request, response, code, msg, hdrs)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 448, in error
return self._call_chain(*args)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 382, in _call_chain
result = func(*args)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/urllib2.py", line 531, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
HTTPError: HTTP Error 409: Conflict
code for the handler that line 66 belongs to:
class GetUpdatesHandler(webapp2.RequestHandler):
def get(self):
urlfetch.set_default_fetch_deadline(60)
self.response.write(json.dumps(json.load(urllib2.urlopen(BASE_URL + 'getUpdates'))))
Totally newbie, any suggestion is appreciated!
You should check what status code & what content is returned by your webhook.
You have 2 options how to reply to use:
Call Telegram API
Return JSON as a response to webhook call
As you have not provided it source code of reply() it's hard to tell what exactly is wrong.
Anyway your webhook should return HTTP status code 200. If it does not Telegram treat it as an internal error and is trying to resent message to you. This is why you are getting repeated calls and it's "replying like crazy".
Most probably the call reply("keep replying this line") is successful but then something wrong and Telegram gets wrong reply.
Add try/except blocks and log exceptions.
Check your logs & put additional logging if needed. For example I'm logging HTTP response content from my webhook. It helps.