How to make a loop for API calls Constantly? - python

I am wondering how do u make a loop for an api call that will keep calling that API, but when I tried making one it didn't work here is the code:
while True:
api_requesting = requests.get("https://api.battlemetrics.com/servers/3411152?include=player", headers=headers)
time.sleep(5)
jsoned_api = api_requesting.json()
function = jsoned_api["included"]
names = []
for person in function:
names.append(person['attributes']['name'])
And this is for e to call upon the request, and parsed it to give me the names of each player etc
#client.command(name='players')
async def createEmbed(ctx):
await ctx.send(f"{len(names)} players are online currently")
urString = ""
for name in names:
urString = urString + "> " + name + "\n"
urString = "```" + urString + "```"
await ctx.send(urString)
So I am wondering how will I make a loop for my request it's all the way at the beginning where it says while true: but when I run it the bot doesn't respond, and doesn't do anything.

If you want your code to stop when the bot does not respond:
success = True
while success:
api_requesting = requests.get("https://api.battlemetrics.com/servers/3411152?include=player", headers=headers)
# Success is True when the response status code is 200
success = api_requesting.status_code==200
But if you want to keep making requests, you can try:
while True:
api_requesting = requests.get("https://api.battlemetrics.com/servers/3411152?include=player", headers=headers)
if api_requesting.status_code == 200:
# Do something when the bot responds
else:
time.sleep(5)
# Do something else when the bot does not respond

Related

How to reply message on discord with python?

I want to make auto chat with 2 account, first I finished coding auto send message to specific channel, second i want to auto reply to first account.
here my code:
token = 'xxx.GImAw0.0G2MaMXjkvOLUAPfXYajK6eM-Lv5rFteEuutwY'
mess = open("messages.txt", "r").read().splitlines()
chd = 'xxx'
for line in mess:
url = 'https://discord.com/api/v9/channels/' + chd + '/messages'
payload = {"content": line, "tts": False}
header = mainHeader(token)
time.sleep(1)
src = requests.post(url, headers=header, json=payload)
if src.status_code == 429:
ratelimit = json.loads(src.content)
print(f"[!]Ratelimit for",
str(float(ratelimit['retry_after'])) + " seconds")
time.sleep(float(ratelimit['retry_after']))
I'm stuck on my coding to add auto reply with second account(token)

Cant reply json on discord.py

Im making a cripto price tracker and i cant make it reply the json that im making with the coin decko URL and Arg1 for example Eternal or SLP, etc.
# bot = scrt.bot
bot = commands.Bot(command_prefix = "!")
login = 0
tokens_dict = {
'morw' : '0x6b61b24504a6378e1a99d2aa2a5efcb1f5627a3a',
'slp' : '0xcc8fa225d80b9c7d42f96e9570156c65d6caaa25',
'pvu' : '0x31471e0791fcdbe82fbf4c44943255e923f1b794',
'eternal' : '0xd44fd09d74cd13838f137b590497595d6b3feea4'
}
# Login
#bot.event
async def on_ready():
global login
print('We have logged in as {0.user}'.format(bot))
login = 1
#bot.command()
async def coin(ctx, arg1):
global tokens_dict
if(arg1 in tokens_dict.keys()):
url = 'https://api.pancakeswap.info/api/v2/tokens/' + tokens_dict[arg1]
response = request.get(url)
responseDict = json.loads(response.text)
await ctx.reply(responseDict)
else:
await ctx.reply("The token " + str(arg1) + " is not in the token list, if you want to add " + str(arg1) + " to the list please use the command : " + '\n' + "!add_token")
In the coin function im trying to reply the json that ive created but i dont know how to.
response = request.get(url)
responseDict = json.loads(response.text)
await ctx.reply(responseDict)
I'm assuming this is the part you're talking about.
You actually don't need to call json.loads(response.text) if you're going to send it anyway. If the raw response is unformatted then you can do this
response_dict = json.loads(response.text)
formatted_dict = json.dumps(response_dict, indent=4)
await ctx.reply(formatted_dict)
This should send the json as a string with indents.
The reason discord.py wasn't letting you send the message was because it wasn't a string.

How to change a particular char in a string?

I am creating a discord bot that gives me gif when I say !gif in a particular channel. The problem I am facing is when I type # it cannot change itself to %23 as it is used in links. I just want a way to change # in the string to %23. Please help me for that. The whole code is given below. I am very new to python so if you want any other errors please fix it and also clean up the code.I am using the tenor API Thank you
Code :
import discord
import os
import json
import requests
import random
client = discord.Client()
global search_term_public
global url
search_term_public = "Rick Roll"
def tenor():
global url
# set the apikey
apikey = (os.getenv("TENORAPIKEY"))
# our test search
search_term = search_term_public
# get the GIFs for the search term
r = requests.get("https://g.tenor.com/v1/search?q=%s&key=%s&contentfilter=high" % (search_term, apikey))
if r.status_code == 200:
# load the GIFs using the urls for the smaller GIF sizes
top_8gifs = json.loads(r.content)
g = len(top_8gifs['results'])
i = random.randint(0,g)
if(i == g):
i = g-1
h = str(g)
f = str(i)
url = top_8gifs['results'][i]['media'][0]['gif']['url']
print("The number picked is " + f +" out of " + h + ". Search Term : " + search_term + ". Url : " +url)
else:
top_8gifs = None
return url
#client.event
async def on_ready():
print("Bot has successfully logged in as {0.user}".format(client))
#client.event
async def on_message(message):
global search_term_public
if message.author == client:
return
if message.content.startswith("!gif") and message.channel.id == 831789159587774504:
# put the search term into the public variable. split the content with space and the second or more than second word should be in a variable
tokens = message.content.split(' ')
if tokens.__contains__(""):
tokens.remove("!gif")
tokens.remove("")
elif tokens.__contains__("#"):
# I want to change # in the token and change it to %23
print()
else :
tokens.remove("!gif")
search_term_public = ("".join(tokens))
if search_term_public == "":
search_term_public = "Rick Roll"
await message.channel.send("You got rick rolled!")
url = tenor()
await message.channel.send(url)
client.run(os.getenv("DISCORDTOKEN"))
Try this, it might work
You can just use the "replace" as follows
elif tokens.__contains__("#"):
token=token.replace("#","%23")
You want to look at
url encoding probably.
However, to directly answer the question as a hotfix, I think you can do this directly after the .split() line
tokens = [token.replace('#', '%23') for token in tokens]

I'm trying to cancel the tasks in running event loop using python asyncio

Hi I'm stuck the problem asyncio. I'm using Python version 3.7.3.
And Sorry for I'm not native speaker at English.
I'm writing a script for get a lyric from genius.
This is my script.
Every requests going to be 6times if I couldn't the result in the end.
I divided get request 2 times almost same time. It means like a 2*3.
Checking the result and if I could get the result I want to stop the other tasks.
Because of to be less request.
So I used cancel() and tried to raise asyncio.exceptions.CancelledError when I got the lyric but It doesn't work well.
It shows RuntimeError: Event loop is closed I don't know why doesn't work well.
Please teach me some one familiar with this situation.
import asyncio
import requests
from bs4 import BeautifulSoup, Comment
#Lyrics__Container-sc-1ynbvzw-2
class Lyric():
def __init__(self, artist, song_name):
self.artist = artist
self.song_name = song_name
self.__gtask = []
self.__canceled = False
self.__lyric = ''
self.genius_url = self.make_genius_url(artist, song_name)
lyric = self.lyric_from_genius(self.genius_url)
print(lyric)
def make_genius_url(self, artist, song_name):
search_song = f'{artist} {song_name}'
search_song = search_song.replace(' ', '-')
print(search_song)
return f'https://genius.com/{search_song}-lyrics'
def get_soup(self, url):
r = requests.get(url)
if r.status_code == 200:
soup = BeautifulSoup(r.content, 'lxml')
return soup
else:
return False
def scrape_genius(self, url):
soup = self.get_soup(url)
if soup and not self.__canceled:
lyric_soup = soup.select('.song_body-lyrics .lyrics p')
if lyric_soup:
self.__canceled = True
tags = lyric_soup[0].find_all(['a', 'i'])
for tag in tags:
tag.unwrap()
print('ここから歌詞です。')
print(lyric_soup[0].text)
self.__lyric = lyric_soup[0].text
self.__gtask.cancel()
else:
print('歌詞情報を取得出来なかった。')
else:
if self.__canceled:
print('歌詞取得した')
else:
print('歌詞情報がない')
self.__gtask.cancel()
def lyric_from_genius(self, url):
async def main_loop(url):
sem = asyncio.Semaphore(2)
async def get_lyric_soup(url):
async with sem:
await self.loop.run_in_executor(None, self.scrape_genius, url)
#main_loopの処理
for _ in range(6):
self.__gtask += [get_lyric_soup(url)]
return await asyncio.gather(*self.__gtask)
try:
self.loop = asyncio.new_event_loop()
self.loop.run_until_complete(main_loop(url))
except asyncio.exceptions.CancelledError as e:
print("*** CancelledError ***", e)
finally:
if self.__lyric:
return self.__lyric
else:
print('5回のリクエストで曲情報が取れなかった。')
Lyric = Lyric('kamal', 'blue')

How do I get this while loop and json response to work?

The first time the script is run with input userid and if the user is online, it runs fine until the print(f'{username}, {userid}' + ' is still online...') gets stuck.
The program never continues to the else: when the user go offline and while userid == str(ps['user_id']): is no longer True.
It's like the str(ps['user_id']): never updates in the script when called.
userid = input('Input userID: ')
response = requests.post('website.com/api', headers=headers, data=data)
json_data = json.dumps(response.json(), indent=2)
data = json.loads(json_data)
while True: # Main loop to run if a user is online
for ps in data['result']['page']['list']:
if userid == str(ps['user_id']): # If a user is online print details
username = ps['nick_name']
print('Username: ' + ps['nick_name'])
print('UserID: ' + str(ps['user_id']))
while userid == str(ps['user_id']): # Look if the user is still online (is in the json response)
print(f'{username}, {userid}' + ' is still online...')
time.sleep(3)
else: # If user go offline(is not in the json response), break and restart main loop(first while loop).
break
print('Waiting for ' + f'{userid}' + ' to get online...') # Message until user go online again (is found in the json response).
time.sleep(5)
You are not updating data anywhere inside of your loop so its using the same stale data for every iteration. You can just add your three lines to generate data into your loop before the time.sleep(5). This will give you updated data and should resolve your issue.
userid = input('Input userID: ')
response = requests.post('website.com/api', headers=headers, data=data)
json_data = json.dumps(response.json(), indent=2)
data = json.loads(json_data)
userList = data['result']['page']['list']
isOnline = 0
while True: # Main loop to run if a user is online
hasLoggedIn = 0
for user in userList:
if str(user['user_id']) == userid and isOnline == 0: # If a user is online print details
username = user['nick_name']
print('Username: ' + user['nick_name'])
print('UserID: ' + str(user['user_id']))
print(f'{username}, {userid}' + ' is now online...')
isOnline = 1
hasLoggedIn = 1
time.sleep(3)
elif str(user['user_id']) == userid and isOnline == 1:
print(f'{username}, {userid}' + ' is still online...')
hasLoggedIn = 1
time.sleep(3)
if hasLoggedIn == 0:
print('Waiting for ' + f'{userid}' + ' to get online...') # Message until user go online again (is found in the json response).
isOnline = 0
time.sleep(5)
response = requests.post('website.com/api', headers=headers, data=data)
json_data = json.dumps(response.json(), indent=2)
data = json.loads(json_data)
userList = data['result']['page']['list']

Categories