Currently this function is searching for a member that starts with the input query. For example, if i input ja, it will output all members that have their names start with ja. However, i am trying to make it so it accounts for all names that have ja in their name. Hence, it will not only include jack, jasper but include kaja, maja etc.
#staticmethod
async def search_members(guild, member) -> typing.List[discord.Member]:
return [i for i in guild.members if str(i).lower().startswith(member.lower())]
You can use the in keyword.
#staticmethod
async def search_members(guild, member) -> typing.List[discord.Member]:
return [i for i in guild.members if member.lower() in str(i).lower()]
NOTE: This looks up the Members username if you want the Nickname of the Member in this specific guild use discord.Member.display_name
Related
I am going to create a discordpy bot that can check users server credit of Tatsu bot
I use Tatsu API to get user's credit, but it has problem that is 'object has no attribute 'credits''. It also appears when I use avatar_url, avatar_hash,...
This is Tatsu library: https://github.com/PumPum7/Tatsu.py
#commands.command()
async def transfer(self,ctx, member: discord.Member):
wrapper = ApiWrapper(key=os.environ['token'])
user_profile = await wrapper.get_profile(member.id)
await ctx.send(user_profile.credits)
I've taken a look at the source code of the library (it's a really bad one to be honest). It seems that when an internal exception is throw, instead of raising and propagating it, the author decided to return it (exact lines are here), I have no idea what the author wanted to do with that, nonetheless you can use a simple if-statement to check if the method didn't return an error:
#commands.command()
async def transfer(self,ctx, member: discord.Member):
wrapper = ApiWrapper(key=os.environ['token'])
user_profile = await wrapper.get_profile(member.id)
if not isinstance(user_profile, Exception):
await ctx.send(user_profile.credits)
else:
exc = user_profile
print(f"An error happened:\n{exc.__class__.__name__}: {exc}")
I have a graphene mutation like this:
class User(ObjectType):
username = String()
class ImportUsers(Mutation):
class Arguments:
users = List(User)
Output = List(User)
#staticmethod
def mutation(root, info, users):
...
But graphene gives me the following error: AssertionError: Mutations.importUsers(users:) argument type must be Input Type but got: [User].
How can I have a mutation in graphene which accepts a list of objects?
I was trying roughly the same thing as you did.
Figured out that custom input types should inherit from graphene.InputObjectType instead of graphene.ObjectType.
class User(graphene.InputObjectType): # <-- Changed to InputObjectType
username = graphene.String()
So, having your User like this should solve the case.
Yeah so, basically, you need to have this:
class User(graphene.ObjectType):
username = graphene.String()
class ImportUsers(Mutation):
class Arguments:
users = graphene.List(User)
Output = graphene.List(User)
#staticmethod
def mutation(root, info, users):
...
Graphene has a List type. Also, I don't know if it's just me or not, but I think you need to have graphene.(type), not just the type. I am working on something very similar right now to this, so hopefully you find or found your solution, and if you do, let me know how it went! Hopefully I helped xD. I am kinda new to all of this so ye
I have 4 intents in my Lex bot , logic of these intents is very similar with slight change in business rules
Is it a good practice to implement one lambda function and based on different intent you can call different functions ?
Can this approach introduce any potential bottle neck or performance impact ?
There are no issues in using a single Lambda function for different intents. You can just call a single lambda function in all the intents, check the intent in that lambda and call relevant function/method in same lambda.
As you told, intents are very similar, so you could probably also use common functions for doing similar things for those intents.
def common_function():
# some processing
return cm
def intent2(intent_request):
cm = common_function()
# rest processing
return output
def intent1(intent_request):
cm = common_function()
# rest processing
return output
def dispatch(intent_request):
logger.debug('dispatch userId={}, intentName={}'.format(intent_request['userId'], intent_request['currentIntent']['name']))
intent_name = intent_request['currentIntent']['name']
if intent_name == 'intent1':
return intent1(intent_request)
if intent_name == 'intent2':
return intent2(intent_request)
if intent_name == 'intent3':
return intent3(intent_request)
if intent_name == 'intent4':
return intent4(intent_request)
raise Exception('Intent with name ' + intent_name + ' not supported')
def lambda_handler(event, context):
logger.debug(event)
logger.debug('event.bot.name={}'.format(event['bot']['name']))
return dispatch(event)
Is it possible to extract the function and arguments of a coroutine object in python3.6?
Context: currently I have something like this:
async def func(*args):
...
ret = await remotely(func, x, y)
Under the hood, remotely pickles func, x, and y, scp's that to a different server, where it unpickles them, executes func(x,y), pickles the result, scp's that back, and finally unpickles it into ret.
This API feels distasteful to me, I'd prefer to have:
ret = await remotely(func(x, y))
I could do this if I could pickle the coroutine object represented by func(x, y), but when I tried that, I get:
TypeError: can't pickle coroutine objects
So my alternate hope is that I can extract f, x, and y from f(x, y), hence this question.
So when you do ret = await remotely(func(x, y)), you actually construct the coroutine object for func. Fortunately, you can extract the information you need from coroutine objects, which you can send over for remote execution.
So first of all you can get the function name using the __qualname__ attribute. This will give you the fully qualified name, i.e. if the coroutine is nested, it will get you the full path to your function.
Next, you can extract the argument values from the frame object of the coroutine.
So this is how your remote function would look like
async def remote(cr):
# Get the function name
fname = cr.__qualname__
# Get the argument values
frame = cr.cr_frame
args = frame.f_locals # dict object
result = await ... # your scp stuff
return result
There is just one caveat. You should indicate that the function should be only used the way that you have posted, i.e.
ret = await remotely(func(x, y))
...in other words, the coroutine should be "fresh", and not half-way executed (which is almost not possible if you initiate it right passing it to remote). Otherwise, the f_locals value might include any other local variable that is defined before any awaits.
Found no clean solution. But we can find function as a referrer to coroutine's code object:
import gc
import inspect
def get_function_from_coroutine(coroutine: Coroutine) -> Callable:
referrers = gc.get_referrers(coroutine.cr_code)
return next(filter(lambda ref: inspect.isfunction(ref), referrers))
def get_kwargs_from_coroutine(coroutine: Coroutine) -> dict[str, Any]:
return coroutine.cr_frame.f_locals
async def foo(a: str, b: int):
return a * b
coro = foo("test", b=2)
print(get_function_from_coroutine(coro)) # <function foo at 0x7ff61ece9820>
print(get_kwargs_from_coroutine(coro)) # {'a': 'test', 'b': 2}
Is it possible to use =LOAD(...) with a function rather then controller/function string
e.g:
Controller:
def test():
print "test"
def index():
return dict(test=test)
View:
{{=LOAD(test, ajax=True)}}
rather then:
View:
{{=LOAD('controller', 'test', ajax=True)}}
The main reason being, I want to use lambda/generated functions which cannot be accessed this way.
No. But not because the syntax is not supported, because it is logically impossible: the LOAD() is executed in a different http request than the one in which the lambda would be executed and therefore the latter would be undefined. Moreover to perform the ajax callback, the called function must have a name, cannot be a lambda. We could come up with a creative use of cache so that LOAD stores the lambda in cache:
def callback():
""" a generic callback """
return cache.ram(request.args(0),lambda:None,None)(**request.vars)
def LOAD2(f,vars={}):
""" a new load function """
import uuid
u = str(uuid.uuid4())
cache.ram(u,lambda f=f:f,0)
return LOAD(request.controller,'callback',args=u,vars=vars,ajax=True)
def index():
""" example of usage """
a = LOAD2(lambda:'hello world')
return dict(a=a)
But this would only work with cache.ram and would require periodic cache cleanup.