Detect failed edit of channel in discord.py - python

I am making a discord bot which lets users edit a voicechannel name. My code is something like this:
channel = client.get_channel(id)
try:
await channel.edit(name="new name")
except:
raise
And it raises fine if the name is invalid but not if the name is valid and the change was not successful due to Discords rate limit of I guess 2 edits every 10 minutes.
I think the problem is that there is no error on my end, Discord is just waiting with the response. Is there a way to give my request a timeout of about 5 seconds and raise if it takes too long?

I would check for both an error and a None response. Better yet, why not just check that the name after the change is what it should be?
I don't think you can add in a timeout directly into the function call but this is the type of thing you might want to loop and add a asyncio.sleep into. Ignoring the first part, you might have something like this:
NEW_NAME = "new name"
while True:
e = None
try:
await channel.edit(name=NEW_NAME)
except Exception as e: pass
# "channel.name" is pseudo-code.
# Use whatever method to check the name.
if <channel.name> != NEW_NAME:
print ("Exception: %s ...(whatever else you want to print)" % e)
await asyncio.sleep(60) # or whatever you think reasonable
else:
break

Related

How to change the message sent by the inline bot?

There is this code:
#bot.inline_handler(lambda query: query.query == 'text')
def query_text(inline_query):
try:
r = types.InlineQueryResultArticle('1', 'text', types.InputTextMessageContent('2'))
bot.answer_inline_query(inline_query.id, [r])
except Exception as e:
print(e)
I do not understand how to make the message "2" be changed, for example, after 2 seconds to "3".
I wanted to do it through bot.edit_message_text () but I didn’t understand where to get all the id from.
You get the inline_message_id parameter of editMessageText by listening for ChosenInlineResult updates.
Also notice that you should do the following things to be able to receive updates like that:
Contact #BotFather and use the /setinlinefeedback command to enable receiving those updates.
Add chosen_inline_result to the allowed_updates parameter when you getUpdates.

Python script stops at error instead of carrying on

I am using Telethon for a telegram bot.
I've got a list of phone numbers. If the phone number is valid then to run a script, if it is invalid I want it to check another number.
This is the part of script which is causing me issues.
from telethon.sync import TelegramClient
from telethon.errors.rpcerrorlist import PhoneNumberBannedError
api_id = xxx # Your api_id
api_hash = 'xxx' # Your api_hash
try:
c = TelegramClient('{number}', api_id, api_hash)
c.start(number)
print('Login successful')
c.disconnect()
break
except ValueError:
print('invalid number')
If the number is invalud then I would expect the script to print 'invalid number' and then carry on. Except it is throwing error 'telethon.errors.rpcerrorlist.PhoneNumberInvalidError: The phone number is invalid (caused by SendCodeRequest)', then ending the script.
How can I carry on the script when this error is thrown?
Thanks
The exception you're catching is ValueError, but the error being thrown is telethon.errors.rpcerrorlist.PhoneNumberInvalidError.
So you need to catch that exception instead:
from telethon.errors.rpcerrorlist import PhoneNumberInvalidError
try:
# your code
except PhoneNumberInvalidError:
print('invalid number')
You can also combine error types if needed:
except (PhoneNumberInvalidError, ValueError):
# handle these types the same way
except TypeError:
# or add another 'except <type>' line to handle this error separately
This is especially useful when you're running a lot of code in your try and so a lot of different errors could occur.
Your last options is to catch every error using
try:
# code
except Exception:
print("exception!")
and while this might seem to be useful it will make debugging a lot harder as this will catch ANY error (which can easily hide unexpected errors) or it will handle them in the wrong way (you don't want to print 'invalid number' if it was actually a TypeError or KeyboardInterrupt for example).

Can't catch an exception, system just closes

I've implemented an orchestrator in python that makes some requisitions to an API. My problem is that sometimes it gets stucked in a request. To solve that I used the timeout parameter. Now I want to implement something so I can retry doing the requisition, but first I need to take care of the exception. For that I tried this:
uri = MS_MONITOR + "/api/monitor/advise/lawsuit/total/withProgressDaily"
try:
response = requests.get(uri, headers={"Correlation-Id": CORRELATION_ID}, timeout = 10)
except requests.exceptions.RequestException as e:
logging.info("[{}] [{}] {}".format("ERROR de Timeout", response.status_code, uri))
print("Deu timeout")
I put the timeout as 10 just to force it to happen, the problem is that it doesn't go into the exception part below, the cmd just closes. I've tried using this one too but it didn't work either:
except requests.exceptions.Timeout
If there's lack of information in my post please let me know so I'll provide it. Thank you!

Nested function call in async way python

I have an api that returns response of pagination only 10 records at a time. I want to process 10 record (index=0 and limit=10) then next 10(index=10 and limit=10) and so on till it returns empty array.
I want to do it in async way.
I am using the following deps:
yarl==1.6.0
Mako==1.1.3
asyncio==3.4.3
aiohttp==3.6.2
The code is:
loop = asyncio.get_event_loop()
loop.run_until_complete(getData(id, token,0, 10))
logger.info("processed all data")
async def getData(id, token, index, limit):
try:
async with aiohttp.ClientSession() as session:
response = await fetch_data_from_api(session, id, token, index, limit)
if response == []:
logger.info('Fetched all data')
else:
# process data(response)
getData(session, id, limit, limit+10)
except Exception as ex:
raise Exception(ex)
async def fetch_data_from_api(
session, id, token, index, limit
):
try:
url = f"http://localhost:8080/{id}?index={index}&limit={limit}"
async with session.post(
url=url,
headers={"Authorization": token}
) as response:
response.raise_for_status()
response = await response.json()
return json.loads(json.dumps(response))
except Exception as ex:
raise Exception(
f"Exception {ex} occurred"
)
I issue is that it works fine for first time but when i am calling the method getData(session, id, limit, limit+10) again from async def getData(id, token, index, limit). It is not been called.
How can i resolve the issue?
There are a few issues I see in your code.
First, and this is what you talk about, is the getData method.
It is unclear to me a bit by looking at the code, what is that "second" getData. In the function definition your arguments are getData(id, token, index, limit), but when you call it from within the function you call it with getData(session, id, limit, limit+10) where the id is the second parameter. Is that intentional? This looks to me like there is another getData method, or it's a bug.
In case of the first option: (a) you probably need to show us that code as well, as it's important for us to be able to give you better responses, and (b), more importantly, it will not work. Python doesn't support overloading and the getData you are referencing from within the wrapping getData is the same wrapping method.
In case it's the second option: (a) you might have an issue with the function parameters, and (b) - you are missing an await before the getData (i.e. await getData). This is actually probably also relevant in case it's the "first option".
Other than that, your exception handling is redundant. You basically just re raise the exception, so I don't see any point in having the try-catch blocks. Even more, for some reason in the first method, you create an Exception from the base exception class (not to be confused with BaseException). Just don't have the try block.

python threading, confirming responses before moving to next line

Recently I have been working to integrate google directory, calendar and classroom to work seamlessly with the existing services that we have.
I need to loop through 1500 objects and make requests in google to check something. Responses from google does take awhile hence I want to wait on that request to complete but at the same time run other checks.
def __get_students_of_course(self, course_id, index_in_course_list, page=None):
print("getting students from gclass ", course_id, "page ", page)
# self.__check_request_count(10)
try:
response = self.class_service.courses().students().list(courseId=course_id,
pageToken=page).execute()
# the response must come back before proceeding to the next checks
course_to_add_to = self.course_list_gsuite[index_in_course_list]
current_students = course_to_add_to["students"]
for student in response["students"]:
current_students.append(student["profile"]["emailAddress"])
self.course_list_gsuite[index_in_course_list] = course_to_add_to
try:
if "nextPageToken" in response:
self.__get_students_of_course(
course_id, index_in_course_list, page=response["nextPageToken"])
else:
return
except Exception as e:
print(e)
return
except Exception as e:
print((e))
And I run that function from another function
def __check_course_state(self, course):
course_to_create = {...}
try:
g_course = next(
(g_course for g_course in self.course_list_gsuite if g_course["name"] == course_to_create["name"]), None)
if g_course != None:
index_2 = None
for index_1, class_name in enumerate(self.course_list_gsuite):
if class_name["name"] == course_to_create["name"]:
index_2 = index_1
self.__get_students_of_course(
g_course["id"], index_2) # need to wait here
students_enrolled_in_g_class = self.course_list_gsuite[index_2]["students"]
request = requests.post() # need to wait here
students_in_iras = request.json()
students_to_add_in_g_class = []
for student in students["data"]:
try:
pass
except Exception as e:
print(e)
students_to_add_in_g_class.append(
student["studentId"])
if len(students_to_add_in_g_class) != 0:
pass
else:
pass
else:
pass
except Exception as e:
print(e)
I need to these tasks for 1500 objects.
Although they are not related to each other. I want to move to the next object in the loop while it waits for the other results to come back and finish.
Here is how I tried this with threads:
def create_courses(self):
# pool = []
counter = 0
with concurrent.futures.ThreadPoolExecutor() as excecutor:
results = excecutor.map(
self.__check_course_state, self.courses[0:5])
The problem is when I run it like this I get multiple SSL errors and other errors and as far as I understand, as the threads themselves are running, the requests never wait to finish and move to the next line hence I have nothing in the request object so it throws me errors?
Any Ideas on how to approach this?
The ssl error occurs her because i was reusing the http instance from google api lib. self.class_service is being used to send a request while waiting on another request. The best way to handle this is to create instances of the service on every request.

Categories