I am new at python so sry if question is stupid but i hope u guys will help me.
Bot not updating status every 5 sec(i put more time like 5 min and it didn't work too). It shows number of servers and not changing to second status.
from discord.ext import commands, tasks
from itertools import cycle
#tasks.loop( seconds = 12 )
async def changeStatus():
status = cycle( [f' on { len(client.guilds) } servers', '~help'] )
await client.change_presence( activity = discord.Activity( type = discord.ActivityType.playing, name = next(status) ) )
#client.event
async def on_ready():
print( 'bot connected' )
changeStatus.start()
Since
status = cycle( [f' on { len(client.guilds) } servers', '~help'] )
is called everytime you call your function, it will be reinterpreted, which means that the next() function always return the first element. To fix this, you will need a different approach. For example, create a global iteration-variable and declare you cycle-list as only a list.
iterationPosition = 0
#tasks.loop( seconds = 12 )
async def changeStatus():
status = [f' on { len(client.guilds) } servers', '~help']
await client.change_presence(activity=discord.Activity(type=discord.ActivityType.playing, name=status[iterationPosition]))
iterationPosition = 0 if (iterationPosition == len(status) - 1) else (iterationPosition + 1)
You will need to keep track if you've reached the end of your list. This is done by the last line of code.
It is not changing the status as you got a Presence Update rate-limit of 5/60secs per-session. These rate-limits are dynamic so don't get too close to them
status = cycle( [f' on { len(client.guilds) } servers', '~help'] ) This line should be outside of the changeStatus function as whenever it is called, it makes [f' on { len(client.guilds) } servers the first item.
Related
This is how the application looks like: [1]: https://i.stack.imgur.com/HUaix.png
[2]: https://i.stack.imgur.com/CYWdS.png
The second [2] image shows how the application should look after pressing the "Connect" button. However, after pressing the button it looks the same (image [1]), although the Discord rich presence starts running.
def rpcstart():
os.system('start-rpc-script.py')
global rpc_on
if rpc_on:
connectbutton.config(image=rpcconnectedimage, state='disabled')
disconnectbutton.config(image=rpcdisconnectimage, state='normal')
else:
connectbutton.config(image=rpcconnectimage)
menubar.entryconfig(1,label="Status: Connected")
This is the part of my script that starts the Discord rich presence. There are no errors or anything similar. It just makes the application unresponsive. Is there any fix for that? Here's the pypresence script that I use:
from pypresence import Presence
import time
start = int(time.time())
client_id = "XXXXXX"
RPC = Presence(client_id)
RPC.connect()
while True:
RPC.update(
details = "▬▬▬▬▬▬▬▬▬▬",
state = "DEMO.",
large_image = "logo_rpc_v2",
large_text = "demo.exe is running!",
small_image = "green_circle_rpc_v2",
small_text = "Online",
start = start,
buttons = [{"label": "example.net ", "url": "https://example.net/"},
{"label": "example.net", "url": "https://example.net"}]
)
time.sleep(60)
Try running your RPC code in a separate thread
from threading import Thread
def _rpc_connect(client_id): # this will be your 'target' function, run in its own thread
start = int(time.time())
RPC = Presence(client_id)
RPC.connect()
while True:
RPC.update(
details = "▬▬▬▬▬▬▬▬▬▬",
state = "DEMO.",
large_image = "logo_rpc_v2",
large_text = "demo.exe is running!",
small_image = "green_circle_rpc_v2",
small_text = "Online",
start = start,
buttons = [
{"label": "example.net ", "url": "https://example.net/"},
{"label": "example.net", "url": "https://example.net"}
],
)
time.sleep(60)
def run_rpc(client_id)
t_rpc = Threading(
target=_rpc_connect,
args=(client_id,),
daemon=True,
)
t_rpc.start() # start the thread
To run the RPC thread, call the run_rpc function as usual
run_rpc(client_id='XXXXXX')
The following Python code (from Read in parallel and write sequentially?) processes (reads) the data for ID 0 to N. There readers run in parallel and it writes the result in the order of ID. How to implement it in C# efficiently?
async def reader(q, id_to_data, data_ready): # Multiple readers are run in parallel
while True:
id = await q.get()
data = await read_async(id)
id_to_data[id] = data
data_ready.set()
async def main():
q = asyncio.Queue()
for id in range(1000):
await q.put(id)
id_to_data = {}
data_ready = asyncio.Event()
readers = [asyncio.create_task(reader(q, id_to_data, data_ready))
for _ in range(3)]
for id in range(1000):
while True:
# wait for the current ID to appear before writing
if id in id_to_data:
data = id_to_data.pop(id)
await data.write_async(f'{id}.csv')
break
# move on to the next ID
else:
# wait for new data and try again
await data_ready.wait()
data_ready.clear()
for r in readers:
r.cancel()
C#:
void main() {
List<int> ids = get_IDs();
ProcessAllIDs(ids);
}
async Task ProcessAllIDs(List<int> ids) {
// A low efficient implementation
for (var id in ids) {
var result = await Process1(id); // Can be run concurrently
await Process2(result); // Need to be run sequentially
}
}
A simple way would be to create a List of Tasks and then await in them in sequence:
var list = new List<Task<int>> { Calculate(2), Calculate(7), Calculate(19) };
foreach(var task in list)
{
Console.WriteLine(await task);
}
static async Task<int> Calculate(int x)
{
await Task.Delay(200);
return x*x;
}
This will start 3 Tasks that calculate stuff simultaneously and then print the results in order.
So for your example, it would look like this:
async Task main() {
List<int> ids = get_IDs();
await ProcessAllIDs(ids);
}
async Task ProcessAllIDs(List<int> ids) {
var tasks = ids.Select(id => Process1(id)).ToList();
for (var t in tasks) {
await Process2(await t); // Need to be run sequentially
}
}
so currently I try to program a calculator but I hit a roadblock. Well, I watched a tutorial by Glowstik on how to make calculator discord bot but it seems that his code doesn't work anymore. So, can anybody suggest changes that I can make to the code to make the bot work? Thanks in advance.
Here is the code :
import discord
import os
from discord.ext import commands, tasks
from online import keep_alive
from discord_slash import SlashCommand
from itertools import cycle
from discord_components import *
import datetime
client = commands.Bot(command_prefix="!")
slash = SlashCommand(client, sync_commands=True)
status = cycle([
" Unanswered Question of Life", " Self - Referential Paradox",
" Near-infinite density?", " Dark matter ?",
" Measurement of the speed of light in one straight line",
" Schrodinger's cat ???",
"The light side of Discord is the path of many unnatural abilities"
])
#client.event
async def on_ready():
print("I have logged in as {0.user}".format(client))
status_swap.start()
DiscordComponents(client)
buttons = [[
Button(style=ButtonStyle.grey, label='1'),
Button(style=ButtonStyle.grey, label='2'),
Button(style=ButtonStyle.grey, label='3'),
Button(style=ButtonStyle.blue, label='+'),
Button(style=ButtonStyle.red, label='Clear')
],
[
Button(style=ButtonStyle.grey, label='4'),
Button(style=ButtonStyle.grey, label='5'),
Button(style=ButtonStyle.grey, label='6'),
Button(style=ButtonStyle.blue, label='-'),
Button(style=ButtonStyle.red, label='Exit')
],
[
Button(style=ButtonStyle.grey, label='7'),
Button(style=ButtonStyle.grey, label='8'),
Button(style=ButtonStyle.grey, label='9'),
Button(style=ButtonStyle.blue, label='×'),
Button(style=ButtonStyle.red, label='←')
],
[
Button(style=ButtonStyle.grey, label='00'),
Button(style=ButtonStyle.grey, label='0'),
Button(style=ButtonStyle.grey, label='.'),
Button(style=ButtonStyle.blue, label='÷'),
Button(style=ButtonStyle.red, label='=')
]]
def calculator(exp):
o = exp.replace('×', '*')
o = o.replace('÷', '/')
result = " "
try:
result = str(eval(o))
except:
result = "An error occurs"
return result
#client.command()
async def operator(ctx):
m = await ctx.send(content="Loading calculator")
expression = "None"
delta = datetime.datetime.utcnow() + datetime.timedelta(minutes = 5)
e = discord.Embed(title="Basic Operation Calculator",description=expression)
await m.edit(components=buttons, embed=e)
while True :
res = await client.wait_for("button click")
while m.created_at < delta :
if res.author.id == int(res.message.embeds[0].title.split("|")[1]) and res.message.embeds[0].timestamp < delta:
expression = res.message.embeds[0].description
if expression == "None" or expression == 'An error occurs':
expression = ''
elif res.component.label == 'Exit':
await res.respond(content='Calculator Closed. Thanks for using Basic Operation Calculator.',type=7)
break
elif res.component.label == "←":
expression = expression[:-1]
elif res.component.label == 'Clear':
expression = None
elif res.component.label == '=':
expression += calculator(expression)
else:
expression = res.component.label
f = discord.Embed(title='Basic Operation Calculator',description=expression)
await res.respond(content='', embed = f, component=buttons, type=7)
# tasks.loop(minutes=5)
async def status_swap():
await client.change_presence(activity=discord.Game(next(status)))
keep_alive()
client.run(os.getenv('MATH_VAR'))
This code looks like it was taken from https://www.youtube.com/watch?v=3BGcgSm9sv0
which coincidentally I have also used.
Your problem arises from your embed title because it's based around your title having a '|' followed by the user's ID.
try changing the embed title from "Basic Operation Calculator" to f"{ctx.message.author}'s calculator|{ctx.message.author.id}" and tell me if that works. I've modified the code I'm using slightly, so this might be wrong, I'm going off of memory here. If that does work, also try f"Basic Operation Calculator|{ctx.message.author.id}" if you want to keep your title name.
This isn't needed but if you also want to add a sliver of text after the '|', you need to change the split statement in
if res.author.id == int(res.message.embeds[0].title.split("|")[1]) and res.message.embeds[0].timestamp < delta:
to the '|' and any text (thats not the ID) directly after.
so if I want to add "ID: " after, then the split statement would be "| ID: ". Sorry if this sounds confusing, the way this code works is very specific, and I'm pretty new to Stack Overflow. Let me know if you run into any errors or have any questions. If nothing else works I'm happy to send you my current code I'm using since It's only slightly modified. Next time you post a question, try your best to be as specific as possible with your question.
I need some help understanding how Django Channels is executing the code. I'm probably missing some understanding of sync vs async as it's not doing what I would expect.
In summary I wanted a consumer that would do the following:
Connect
On message from client
in a while loop:
execute a long running function (1 sec)
call group_send broadcasting results
This wasn't working, so I tried to create a very simple consumer to understand what's happening.
I create a WebsocketConsumer as I think I want it to run syncronously, i.e. I want each loop to execute and then broadcast the results, then execute again.
When I trigger the receive method I see the self.send happen instantly, but both the "2. First Group Call" and the "3. Second Group Call" happen after the long running function. I can see from the timestamps in the console.log that the chat_message() is only being executed for the "2. First Group Call" after the long running function, even though it appears before the long running function in the receive method.
The results in one of the browser console is:
received "1. Self send 21:45:22.060500"
received "2. 21:45:22.060500 first group call chat start: 21:45:24.529500"
received "3. 21:45:22.060500 second group send lrf start_time: 21:45:22.348000 lrf end_time: 21:45:24.349500 chat start: 21:45:24.537000"
The timestamps in bold are the timestamp when the receive method was started.
The "chat start" timestamp is when chat_message method is called.
class MyConsumer(WebsocketConsumer):
groups = ["my_group"]
def connect(self):
print("connected")
self.accept()
def receive(self, text_data=None, bytes_data=None):
ts = datetime.now().strftime("%H:%M:%S.%f")
self.send(text_data=json.dumps("1. Self send {}".format(ts)))
text_data = "2. {} first group call".format(ts)
async_to_sync(self.channel_layer.group_send)(
"my_group",
{
"type": "chat.message",
"text": text_data,
},
)
text_data = self.long_running_function(ts)
async_to_sync(self.channel_layer.group_send)(
"my_group",
{
"type": "chat.message",
"text": text_data,
},
)
def disconnect(self, close_code):
print("disconnected")
async_to_sync(self.channel_layer.group_discard)("my_group", self.channel_name)
def chat_message(self, event):
chat_msg_start_time = datetime.now().strftime("%H:%M:%S.%f")
text_data = "{} chat start: {}".format(event["text"], chat_msg_start_time)
self.send(text_data=json.dumps(text_data))
def long_running_function(self, ts):
start_time = datetime.now().strftime("%H:%M:%S.%f")
time.sleep(2)
end_time = datetime.now().strftime("%H:%M:%S.%f")
msg = "3. {} second group send lrf start_time: {} lrf end_time: {}".format(ts, start_time, end_time)
return msg
I have a task wherein I have to make 700 REST API calls. I have used a loop, but the run time of the loop is more than the timeout of AWS Lambda service. Is there any way I can make the calls concurrently and merge the results. I am using node JS, but a solution in python is also welcome
Here is a sample of the code I am running now:
HitBTCData = {}
for item in exchanges:
itemlist = item.split('-')
response = requests.get('https://min-
api.cryptocompare.com/data/histominute?
fsym='+itemlist[0]+'&tsym='+itemlist[1]+'&limit=2000&aggregate=1
&e=HitBTC').json()
if itemlist[0]+itemlist[1] not in HitBTCData:
HitBTCData[itemlist[0]+itemlist[1]] = []
HitBTCData[itemlist[0]+itemlist[1]].append(response['Data'])
while response['Type'] != 1:
time = response['TimeFrom']
response = requests.get('https://min-
api.cryptocompare.com/data/histominute?
fsym='+itemlist[0]+'&tsym='+itemlist[1]+
'&limit=2000&aggregate=1&toTs='+str(time)+'&e=HitBTC').json()
if response['Type'] != 1:
HitBTCData[itemlist[0]+itemlist[1]]
.append(response['Data'])
HitBTCData[itemlist[0]+itemlist[1]] =
HitBTCData[itemlist[0]+itemlist[1]][::-1]
Use a loop in Node.js and the calls will run concurrently, but to make sure all of your calls are processed before exiting the lambda, you need to have some form of counter to make sure all of the queries have ended.
example:
var request = require('request');
var results = [];
var runningQueries = 0;
exchanges.forEach(function (item) {
++runningQueries;
callAPI (item, function (err, data) {
if (err) {
results.push(err)
--runningQueries;
} else {
results.push(data)
--runningQueries;
}
if (runningQueries == 0) {
// all call results have been collated, so do something
}
})
})
You'll need to build your own callAPI function. Also, I'm being a bit lazy with what I'm pushing to the array here, but it's just to give you a framework.
You could very easily do this with Promise.all():
const urls = [...];
const requestFunction = async (url) => {
// all your ifs go here
let data = await request(url);
// transform/sanitize your data
return data;
}
const allResults = await Promise.all(urls.map(requestFunction));
// you now have an array of results
The only downside to Promise.all() is that if any of the promises rejects, everything fails. So I would suggest catching errors and resolving with null or something similar.
You could do a for loop to generate your array of URLs, new Array(700).map(...), or since it looks like you already have some kind of array, just .map() that directly and do more transforms inside the request function.