How To Get The Member Count Discord.py - discord.py

I am trying to add a status in my discord bot, which shows the total number of members, the bot is watching like all bots show for exmaple.
If my bot is added in 2 servers, 1st one has 20 members, second one has 30 members.
= 50 Members Total, How Can I show this???? Can anybody help??
Proof That The Code Is 100% Working
def find_members():
l = str(client.guilds)
l = l.split(" ")
f = 0
for i in range(len(l)):
if "member_count=" in l[i]:
s = l[i]
d = ""
for i in s:
if i.isnumeric():
d += i
else:
pass
f += int(d)
else:
pass
return f

Your function can be simplified significantly. Guild has a member_count property which is the number of members in the guild. You do have to have the members intent enabled for that though. But using that, getting the member count is trivial.
There's also no need to make the list of guilds a list and then make it a list again - just iterate over it directly. With Python, we can iterate over the items in a list doing for thing in things so we don't need to use range here either; there's no real need to know the index of the guild in the list.
def find_members(client: discord.Client) -> int:
total_member_count = 0
for guild in client.guilds:
total_member_count += guild.member_count
return total_member_count
You can now call the find_members function and pass in the client (or remove it and rely on the client already defined in the file).

I've found a solution which you can use to get the total count of members a bot is watching
def find_members():
l = str(client.guilds)
l = l.split(" ")
f = 0
for i in range(len(l)):
if "member_count=" in l[i]:
s = l[i]
d = ""
for i in s:
if i.isnumeric():
d += i
else:
pass
f += int(d)
else:
pass
return f
For Proof Checkout The Image URL In The Question!

so there is a easy method by using bot.users function, the only thing you need is to enable server member intent on the discord bot dashboard and then just add this piece of code,
len(bot.users)

Related

Python: Printing vertically

The final code will print the distance between states. I'm trying to print the menu with the names of the states numbered and vertically. I really struggle to find my mistakes.
This code doesn't raise any error, it just prints nothing, empty.
state_data = """
LA 34.0522°N 118.2437°W
Florida 27.6648°N 81.5158°W
NY 40.7128°N 74.0060°W"""
states = []
import re
state_data1 = re.sub("[°N#°E]", "", state_data)
def process_states(string):
states_temp = string.split()
states = [(states_temp[x], float(states_temp[x + 1]), float(states_temp[x + 2])) for x in
range(0, len(states_temp), 3)]
return states
def menu():
for state_data in range(state_data1):
print(f'{state_data + 1} {name[number]}')
My first guess is, your code does not print anything without errors because you never actually execute process_airports() nor menu().
You have to call them like this at the end of your script:
something = process_airports(airport_data1)
menu()
This will now raise some errors though. So let's address them.
The menu() function will raise an error because neither name nor number are defined and because you are trying to apply the range function over a string (airport_data1) instead of an integer.
First fixing the range error: you mixed two ideas in your for-loop: iterating over the elements in your list airport_data1 and iterating over the indexes of the elements in the list.
You have to choose one (we'll see later that you can do both at once), in this example, I choose to iterate over the indexes of the list.
Then, since neither name nor number exists anywhere they will raise an error. You always need to declare variables somewhere, however, in this case they are not needed at all so let's just remove them:
def menu(data):
for i in range(len(data)):
print(f'{i + 1} {data[i]}')
processed_airports = process_airports(airport_data1)
menu(processed_airports)
Considering data is the output of process_airports()
Now for some general advices and improvements.
First, global variables.
Notice how you can access airport_data1 within the menu() function just fine, while it works this is not something recommended, it's usually better to explicitly pass variables as arguments.
Notice how in the function I proposed above, every single variable is declared in the function itself, there is no information coming from a higher scope. Again, this is not mandatory but makes the code way easier to work with and understand.
airport_data = """
Alexandroupoli 40.855869°N 25.956264°E
Athens 37.936389°N 23.947222°E
Chania 35.531667°N 24.149722°E
Chios 38.343056°N 26.140556°E
Corfu 39.601944°N 19.911667°E"""
airports = []
import re
airport_data1 = re.sub("[°N#°E]", "", airport_data)
def process_airports(string):
airports_temp = string.split()
airports = [(airports_temp[x], float(airports_temp[x + 1]), float(airports_temp[x + 2])) for x in
range(0, len(airports_temp), 3)]
return airports
def menu(data):
for i in range(len(data)):
print(f'{i + 1} {data[i]}')
# I'm adding the call to the functions for clarity
data = process_airports(airport_data1)
menu(data)
The printed menu now looks like that:
1 ('Alexandroupoli', 40.855869, 25.956264)
2 ('Athens', 37.936389, 23.947222)
3 ('Chania', 35.531667, 24.149722)
4 ('Chios', 38.343056, 26.140556)
5 ('Corfu', 39.601944, 19.911667)
Second and this is mostly fyi, but you can access both the index of a iterable and the element itself by looping over enumerate() meaning, the following function will print the exact same thing as the one with range(len(data)). This is handy if you need to work with both the element itself and it's index.
def menu(data):
for the_index, the_element in enumerate(data):
print(f'{the_index + 1} {the_element}')

message.reaction.count Discord py

I'm trying to make a simple bot that would only react to messages with attachments. Then after a certain time, it would make a link to the message and send it on a moderation channel if it got 2 or more reactions.
#client.event
async def on_message(message):
if message.channel.id == 828579458167996420:
if message.attachments or "http" in message.content:
msgID = message.id
await message.add_reaction("<:uut:828580756384120912>")
await asyncio.sleep(200)
x = int
if message.reactions.count(x) >= 3:
link = 'https://discord.com/channels/11223345678900/828579458167996420/' + str(msgID)
channel = client.get_channel(892065611876823100)
x = x - 1
await channel.send("this post " + str(link) + "is liked " + str(x) + "times." )
the bot reacts to the messages i want, but it doesn't post anything in the moderation channel
I'm a beginner, sry for the messy codes :\
If you are not getting any kinds of errors, the issue lays right here, the if statement never gets triggered:
x = int
if message.reactions.count(x) >= 3:
message.reactions will return a list, your statement would count how many times x is in that list (which is always zero).
What you wanna do instead is just to get the total length of that list, like this:
if len(message.reactions) >= 3:
Also other small improvement tip: You can get the URL of a message with message.jump_url
EDIT:
Sorry, what you actually need to do to get the reaction count is to either search the emoji you want to count, or the shortcut would be to just get the first reaction in that list, since your bot should be the first to react to that message anyways:
#this will return a list of reactions that match the emoji you want
emoji = [x for x in message.reactions if str(x.emoji) == '😂'] #replace the emoji with the one you want
print(emoji[0].count) #counts the first (and only) emoji in the new list
"Shortcut" version, just gets the first reaction count:
print(message.reactions[0].count)

How to detect number in certain range

Trying to get bot to send a message when the person sends a message in range
async def on_message(message):
if 0 < Message < 100 in message.content:
await bot.message.send(message.channel, "you are in Bronze 1")
Ok first of all. Please don't code on mobile. Especially not python. That will mess things up way too much.
Second, please define your variables properly. Message is not a defined variable. It will return an error.
So, as you said, you wanted two ways to do this. The number should be the message itself, or within the message.
For the first example, all you have to do is cast the message.content to int. Then you can check if it's in the range.
if 0 < int(message.content) < 100:
...
For the second example, you will have to do something similar, however, you should split the entire message.content string and convert the number ones into integers. I'm assuming that the number will not be within a word and it will be by itself.
for word in message.content.split():
if word.isnumeric():
num = int(word)
if 0 < num < 100:
... # return and send message to avoid spamming

PyMC3: How can I code my custom distribution with observed data better for Theano?

I am attempting to implement a fairly simple model in pymc3. The gist is that I have some data that is generated from a sequence of random choices. The choices can be thought of as a multinomial, and the process selects choices as a function of previous choices.
The overall probability of the categories is modeled with a Dirichlet prior.
The likelihood function must be customized for the data at hand. The data are lists of 0's and 1's that are output from the process. I have successfully made the model in pymc2, which you can find at this blog post. Here is a python function that generates test data for this problem:
ps = [0.2,0.35,0.25,0.15,0.0498,1/5000]
def make(ps):
out = []
while len(out) < 5:
n_spots = 5-len(out)
sp = sum(ps[:n_spots+1])
P = [x/sp for x in ps[:n_spots+1]]
l = np.argwhere(np.random.multinomial(1,P)==1).ravel()[0]
#if len(out) == 4:
# l = np.argwhere(np.random.multinomial(1,ps[:2])==1).ravel()[0]
out.extend([1]*l)
if (out and out[-1] == 1 and len(out) < 5) or l == 0:
out.append(0)
#print n_spots, l, len(out)
assert len(out) == 5
return out
As I'm learning/moving to pymc3, I'm trying to input my data as observed into a custom likelihood function, and I'm running into several issues along the way. It's probably because this is my first experience with Theano, but I'm hoping that someone can give some advice.
Here is my code (using the make function above):
import numpy as np
import pymc3 as pm
from scipy import optimize
import theano.tensor as T
from theano.compile.ops import as_op
from collections import Counter
# This function gets the attributes of the data that are relevant for calculating the likelihood
def scan(value):
groups = []
prev = False
s = 0
for i in xrange(5):
if value[i] == 0:
if prev:
groups.append((s,5-(i-s)))
prev = False
s = 0
else:
groups.append((0,5-i))
else:
prev = True
s += 1
if prev:
groups.append((s,4-(i-s)))
return groups
# The likelihood calculation for a single data point
def like1(v,p):
l = 1
groups = scan(v)
for n, s in groups:
l *= p[n]/p[:s+1].sum()
return T.log(l)
# my custom likelihood class
class CustomDist(pm.distributions.Discrete):
def __init__(self, ps, data, *args, **kwargs):
super(CustomDist, self).__init__(*args, **kwargs)
self.ps = ps
self.data = data
def logp(self,v):
all_l = 0
for v, k in self.data.items():
l = like1(v,self.ps)
all_l += l*k
return all_l
# model creation
model = pm.Model()
with model:
probs = pm.Dirichlet('probs',a=np.array([0.5]*6),shape=6,testval=np.array([1/6.0]*6))
output = CustomDist("rolls",ps=probs,data=data,observed=True)
I am able to find the MAP in about a minute or so (my machine is Windows 7, i7-4790 #3.6GHz). The MAP matches well with the input probability vector, which at least means the model is linked properly.
When I try to do traces, though, my memory usage skyrockets (up to several gig) and I haven't actually been patient enough for the model to finish compiling. I've waited 10 minutes + for the NUTS or HMC to compile before even tracing. The metropolis stepping works just fine, though (and is much faster than with pymc2).
Am I just being too hopeful for Theano to be able to handle for-loops of non-theano data well? Is there a better way to write this code so that Theano plays well with it, or am I limited because my data is a custom python type and can't be analyzed with array/matrix operations?
Thanks in advance for your advice and feedback. Please let me know what might need clarification!

What is the most optimized method to loop through this code?

stocks is a dict():
stocks[0]: [u'portfolio1', u'Active']
stocks[1]: [u'portfolio2', u'Active']
stocks[2]: [u'portfolio3', u'Inactive']
I am trying to check the status of the portfolio which is stocks[0][1], stocks[1][1] and stocks[2][1] and create a list of elements containing only the active portfolio.
And, I am using a counter to do the iteration which seems to be a very slow process. What is the most efficient method to loop through this code?
a = 0
test = {}
while a <= 500:
try:
if stocks[a][1] == 'Active':
test[a] = stocks[a][0]
print test[a]
a +=1
else:
pass
a +=1
except KeyError:
break
test = list(test.values())
test = str(','.join(test)).split(',')
One thing you could try is instead of using a counter is to iterate through the dictionary values themselves, returning only those portfolios with a status of Active. When you find yourself needing to check all of the items in a particular data structure, it is usually easiest to iterate over the structure itself instead of using a counter (i.e. saying for item in iterable instead of for x in range(len(iterable)): iterable[x]):
In [1]: stocks = {
...: 0: [u'portfolio1', u'Active'],
...: 1: [u'portfolio2', u'Active'],
...: 2: [u'portfolio3', u'Inactive']
...: }
In [2]: actives = [x[0] for x in stocks.itervalues() if x[1] == 'Active']
In [3]: actives
Out[3]: [u'portfolio1', u'portfolio2']
actives in this cause is generated using a list comprehension that iterates through the values of the stocks dictionary and returns only those where x[1] (the status, in your case) is equal to Active.

Resources