if before.roles != after.roles:
with open("log.json", 'r') as f:
ac = json.load(f)
for key in ac:
if int(key) == after.guild.id:
# for key in ac:
channel = client.get_channel(ac[key])
#embed = discord.Embed(
# colour = COLOR
#)
#embed.set_author(name=NAME)
#embed.set_thumbnail(url=PFP)
#embed.add_field(name="Old nickname", value=f"{before.display_name}", inline=True)
#embed.add_field(name="New nickname", value=f"{after.display_name}", inline=True)
await channel.send(f"{before.roles}, {after.roles}")
#await channel.send(embed=embed)
I just keep getting this.
How would I make it show the role that was removed/added without all the other junk?
If you want to print just all the role names, then you can use the join function and pass in the roles as the iterable.
For example, the below will send before and after roles, where the roles are joined by a comma:
before_roles = ",".join([role.name for role in before.roles])
after_roles = ",".join([role.name for role in after.roles])
await channel.send(f"{before_roles}, {after_roles}")
Related
This code:
usr = await app.resolve_peer(uid)
udata = InputUser(user_id=usr.user_id, access_hash=usr.access_hash)
r = await app.invoke(functions.messages.DeleteChatUser(chat_id=chan, user_id=udata))
print(r)
Returns:
AttributeError: 'InputPeerChannel' object has no attribute 'to_bytes'
In docs:
class pyrogram.raw.functions.messages.DeleteChatUser**
Deletes a user from a chat and sends a service message on it.
Parameters:
chat_id (int 64-bit) – Chat ID.
user_id (InputUser) – User ID to be deleted.
revoke_history (bool, optional) – Remove the entire chat history of the specified user in this chat.
What`s wrong?
Maybe my udata in the wrong type?
I'm not sure, but "DeleteChatUser" it seems to only work for groups, not channels.
For groups maybe working code:
cid = -10083757838484 # Example group_id
usr = await app.resolve_peer(uid)
if cid < 0:
cid = cid * (-1) # Removing a minus from group_id
udata = InputUser(user_id=usr.user_id, access_hash=usr.access_hash)
r = await app.invoke(functions.messages.DeleteChatUser(chat_id=cid, user_id=udata))
print(r)
But I needed a solution for the channel, so I used:
r = await app.ban_chat_member(int(cid), int(usr))
I have made a telegram member scraper and inviter with Python. It was successful on some tests, but there are times my accounts get banned with upon seeing this error message:
AttributeError: 'ChatForbidden' object has no attribute 'access_hash'
I'm not sure why would it show ChatForbidden if I am already an admin of a group. It's hard to test these as I had to buy new phone numbers every time.
Here's a sample and explanation of my code to invite members to a group:
# Log in into the telegram account
client = TelegramClient('Tg_scraper', api_id, api_hash)
chats = []
last_date = None
chunk_size = 200
groups = []
hash_list = []
# Get all the groups/channel of the account
result = client(GetDialogsRequest(
offset_date=last_date,
offset_id=0,
offset_peer=InputPeerEmpty(),
limit=chunk_size,
hash=0
))
chats.extend(result.chats)
# Puts all the group/channel into a list
i = 0
print('Enter a NUMBER to choose a group where the members will be invited into:')
for chat in chats:
try:
groups.append(chat)
hash_list.append(chat.access_hash)
print(f"({i})" + ' - ' + chat.title)
i += 1
except:
continue
g_index = input("Enter a Number: ")
target_group = groups[int(g_index)]
target_group_entity = InputPeerChannel(target_group.id, target_group.access_hash)
Upon the last line, target_group_entity = InputPeerChannel(target_group.id, target_group.access_hash) is where I encounter the error I have stated above. Upon receiving that error, I get banned.
Does this have something to do with permissions? Do new accounts get banned for botting? It works on my first few tests, but then now I can't invite. Thank you so much for anyone who could help in advance.
I am already an admin of a group
This error is unrelated to your permission level.
Upon the last line is where I encounter the error
Wrong. you encounter this error because you're not coding it right with types in mind, expecting all your .chats are groups. Telegram doesn't tell you what fields exactly have, as you see in this error.
You must use type checking to limit your chats objects to only what you expect, your try block is appending then erroring, so, rather than a plain:
except:
continue
you need to actually confirm it won't error when accessing fields.
print('Enter a NUMBER to choose a group where the members will be invited into:')
i = 0
for chat in chats:
if isinstance(chat, telethon.types.Channel):
if chat.broadcast: continue # ignore non-group
groups.append(chat)
hash_list.append(chat.access_hash)
print(f"({i})" + ' - ' + chat.title)
i += 1
g_index = input("Enter a Number: ")
target_group = groups[int(g_index)]
Ok, so I'm having an issue with my bot. I know what it is, but I don't know what the string to fix it is.
Basically I have it set to store config and prefixes and such in a json but the help command which is loading one of my commands multiple times.
I've checked the help command and i don't think that's it. Because after redoing my setprefix command (which is being displayed multiple times) it added yet another one on so now it's even worse.
Here is my storage system that I believe to be causing the issue.
with open("./config/config.json", "r") as configjsonFile:
configData = json.load(configjsonFile)
login_token = configData["discordtoken"]
with open("./config/prefixes.json") as f:
prefixes = json.load(f)
default_prefix = "-"
def prefix(client, message):
id = message.guild.id
return prefixes.get(id, default_prefix)
client = commands.Bot(command_prefix=prefix)
client.remove_command('help')
#client.command(name="setprefix", aliases=["Prefix", "prefix"])
#commands.has_permissions(administrator=True)
async def setprefix(ctx, new_prefix):
"""Change the server prefix for the bot.
Alt : Prefix, prefix
Usage : prefix <custom prefix>"""
prefixes[ctx.message.guild.id] = new_prefix
with open("./config/prefixes.json", "w") as f:
json.dump(prefixes, f, indent=4)
embed = discord.Embed(color=0x4a3d9a, timestamp=ctx.message.created_at)
embed.set_author(name=f"{client.user.name}", icon_url=client.user.avatar_url)
embed.add_field(name="Success", value=f"Successfully changed prefix changed to `{new_prefix}`")
embed.set_thumbnail(url=client.user.avatar_url)
embed.set_footer(text="NewHorizon Development | https://newhorizon-development.netlify.app", icon_url=client.user.avatar_url)
await ctx.message.delete()
await ctx.send(embed=embed, delete_after=4)
and here is my custom help command just in case I'm wrong about what is causing the issue.
#commands.command(name="help", aliases=["Help", "H", "h"])
#commands.has_permissions(add_reactions=True, embed_links=True)
async def help(self, ctx, *cog):
"""Gets all cogs and commands.
Alt : h, H, Help
Usage : [h]elp <cog or command>"""
try:
if not cog:
"""Cog listing. What more?"""
embed = discord.Embed(title='Cog Listing and Uncatergorized Commands',
description='Use `help <cog>` to find out more about them!\n(BTW, the Cog Name Must Be in Title Case, Just Like this Sentence.)')
cogs_desc = ''
for x in self.client.cogs:
cogs_desc += ('{} - {}'.format(x, self.client.cogs[x].__doc__) + '\n')
embed.add_field(name='Cogs', value=cogs_desc[0:len(cogs_desc) - 1], inline=False)
cmds_desc = ''
for y in self.client.walk_commands():
if not y.cog_name and not y.hidden:
cmds_desc += ('{} - {}'.format(y.name, y.help) + '\n')
embed.add_field(name='Uncatergorized Commands', value=cmds_desc[0:len(cmds_desc) - 1], inline=False)
await ctx.message.add_reaction(emoji='✉')
await ctx.message.author.send('', embed=embed)
else:
"""Helps me remind you if you pass too many args."""
if len(cog) > 1:
embed = discord.Embed(title='Error!', description='That is way too many cogs!', color=discord.Color.red())
await ctx.message.author.send('', embed=embed)
else:
"""Command listing within a cog."""
found = False
for x in self.client.cogs:
for y in cog:
if x == y:
embed = discord.Embed(title=cog[0] + ' Command Listing', description=self.client.cogs[cog[0]].__doc__)
for c in self.client.get_cog(y).get_commands():
if not c.hidden:
embed.add_field(name=c.name, value=c.help, inline=False)
found = True
if not found:
"""Reminds you if that cog doesn't exist."""
embed = discord.Embed(title='Error!', description='How do you even use "' + cog[0] + '"?', color=discord.Color.red())
else:
await ctx.message.add_reaction(emoji='✉')
await ctx.message.author.send('', embed=embed)
except:
await ctx.send("Excuse me, I can't send embeds.")
I am using the rewrite branch if it helps. And my setprefix command IS NOT in a cog, unlike the rest of my commands. Thus why they appear a slight bit different.
Now I'm ASSUMING my issue is that the json are not closing, which I need to know how to make them close, but if that's not the issue, I would very much appreciate someone helping me figure out what's going wrong.
I'm trying to make translate bot using twitchdev python code: https://github.com/twitchdev/chat-samples/blob/master/python/chatbot.py
I was able to get messages from channels and send translated text, but I cannot join multiple channels.
What I did below is making list of channels and call using for loop, but it only join to the last channel.
I tried to make another list of channels in def on_welcome(self, c, e) but it also works on the last channel (when I print self.channels in def on_welcome(self, c, e) it printed blank list, and when I print self.channel it only printed last channel)
Any suggestions are welcome.
import sys
import irc.bot
import requests
import config
class TwitchBot(irc.bot.SingleServerIRCBot):
def __init__(self, username, client_id, token, channels):
for channel in channels
self.client_id = client_id
self.token = token
self.channel = '#' + channel
# Get the channel id, we will need this for v5 API calls
url = 'https://api.twitch.tv/kraken/users?login=' + channel
headers = {'Client-ID': client_id, 'Accept': 'application/vnd.twitchtv.v5+json'}
r = requests.get(url, headers=headers).json()
self.channel_id = r['users'][0]['_id']
# Create IRC bot connection
server = 'irc.chat.twitch.tv'
port = 6667
print 'Connecting to ' + server + ' on port ' + str(port) + '...'
irc.bot.SingleServerIRCBot.__init__(self, [(server, port, 'oauth:'+token)], username, username)
def on_welcome(self, c, e):
print 'Joining ' + self.channel
# You must request specific capabilities before you can use them
c.cap('REQ', ':twitch.tv/membership')
c.cap('REQ', ':twitch.tv/tags')
c.cap('REQ', ':twitch.tv/commands')
c.join(self.channel)
def on_pubmsg(self, c, e):
# If a chat message starts with an exclamation point, try to run it as a command
if e.arguments[0][:1] == '!':
cmd = e.arguments[0].split(' ')[0][1:]
print 'Received command: ' + cmd
self.do_command(e, cmd)
return
def do_command(self, e, cmd):
c = self.connection
# Provide basic information to viewers for specific commands
elif cmd == "raffle":
message = "This is an example bot, replace this text with your raffle text."
c.privmsg(self.channel, message)
elif cmd == "schedule":
message = "This is an example bot, replace this text with your schedule text."
c.privmsg(self.channel, message)
def main():
if len(sys.argv) != 5:
print("Usage: twitchbot <username> <client id> <token> <channel>")
sys.exit(1)
username = config.twitch['botname']
client_id = config.twitch['cliendID']
token = config.twitch['oauth']
channels = ["channel1", "channel2"]
bot = TwitchBot(username, client_id, token, channels)
bot.start()
if __name__ == "__main__":
main()
In your main() function, you are establishing an object of the bot:
bot = TwitchBot(username, client_id, token, channels)
Instead of passing multiple channels to the same bot object, create multiple bot objects with single channels. I haven't tested this yet because Twitch updated their OAuth protocol and I haven't been through the docs.
You may need to thread them, and depending on what functions you implement it may not be thread-safe (just test before going into production). That'd probably look something like:
import threading
t1 = threading.Thread(target=TwitchBot, args=(username, client_id, token, channel1))
t2 = threading.Thread(target=TwitchBot, args=(username, client_id, token, channel2))
t1.setDaemon(True)
t2.setDaemon(True)
t1.start()
t2.start()
Once again, I haven't tested any of this but will likely have time in a few weeks to patch this in my own code after the holiday.
im trying to deal with both InlineKeyboardButton callback_data, and free text data..here's my scenario:
prompting an InlineKeyboard with several buttons, the user clicks one button and then asked to input some free text for the BE to be used.
I have tried to use CallbackQueryHandler(several InlineKeyboardMarkup in the callback function) as an entry point for ConversationHandler which then trigger MessageHandler, with no much success..
I need to catch the free text update (basically wait for user input).
def start(update, context):
keyboard = [[InlineKeyboardButton("bal bla", callback_data='1'),
InlineKeyboardButton("bla bla", callback_data='2')],
[InlineKeyboardButton("bla bla)", callback_data='3'),
InlineKeyboardButton("bla bla", callback_data= '4')],
[InlineKeyboardButton("bla bla", callback_data='5')]]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text('Please choose:', reply_markup=reply_markup)
reply_text = {'text': ''}
def reply_message(update, context):
message = update.message.text
reply_text['text'] = message
return reply_text['text']
def button(update, context, user_data):
query = update.callback_query
query.edit_message_text(text="Loading....\n \r")
if query.data == '1':
pass
elif query.data == '2':
pass
elif query.data == '3':
keyboard = [[InlineKeyboardButton('BBB', callback_data='21'),
InlineKeyboardButton('GGG', callback_data='22')],
[InlineKeyboardButton('PPP', callback_data='23')]]
reply_markup1 = InlineKeyboardMarkup(keyboard)
query.edit_message_text('Please select:', reply_markup=reply_markup1)
elif query.data == '21':
query.edit_message_text('input customer name ')
return 1
if : #no idea which condition to give here
print(reply_text['text'], '\n ^ new free text message here ^')
def main():
conv_handler= ConversationHandler(
entry_points=[
CallbackQueryHandler(button)
],
states={
1 : [MessageHandler(Filters.text, reply_message)],
},
fallbacks= []
)
try:
updater = Updater(bot_token, use_context=True)
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(CallbackQueryHandler(button))
updater.dispatcher.add_handler(conv_handler)
updater.start_polling()
updater.idle()
except Exception as e:
print(e)
Hey i solved this with making a function to parse the user input and remember the input with the user_data method of context.
def check_user_input(update, context):
# get last user text
user_input = update.message.text
# get user_data context
user_data = context.user_data
# set new context user_input
user_data['user_input'] = user_input
context.user_data['user_input'] = user_data['user_input']
if "Text" in user_input:
# do something... i.e reply w/o keyboard
update.message.reply_text(
("{}?!, sounds interesting, tell me more".format(
user_input)))
return GUEST_CHOICE
else:
# ask again
reply_keyboard = [['Text'],['Done']]
markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
update.message.reply_text(
("{}?!, i dont know anything...".format(
user_input),reply_markup=markup))
return CHECK_CHOICE
This seems to be the favorized method to handle and remember user inputs.
This function can now be called within the ConversationHandler/MessageHandlers as you need. You only have to return to a specified ConversationHandler state. So i will make two states, a GUEST_CHOICE and a CHECK_CHOICE state, to handle a single user input validation as example.
conv_handler = ConversationHandler(
entry_points=[CommandHandler('start', start)],
states={
# Ask Guest
GUEST_CHOICE: [MessageHandler(Filters.regex('^(Text)$'),
guest_choice),
],
# Verify input
CHECK_CHOICE: [MessageHandler(Filters.text,
check_user_input),
],
},
fallbacks=[MessageHandler(Filters.regex('^Done$'), done, CommandHandler('start', start))],
allow_reentry = False,
per_user=True,
conversation_timeout=3600,
name="test"
)
As defined, /start is used as user to start the conversationhandler. This calls a start() method i.e.:
def start(update, context):
reply_keyboard = [['Text'],['Done']]
markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
# Setup keyboard and reply
update.message.reply_text(
("Hey {}, how can i help you?".format(
update.message.chat['first_name'])),
reply_markup=markup)
return CHECK_CHOICE
start() will setup the markup keyboard and any input after will be handled with CHECK_CHOICE state, which will call check_user_input here (see above). This will return GUEST_CHOICE and so it will call guest_choice() i.e.:
def guest_choice(update, context):
user_data = context.user_data
# Check authentication request
if "bob" in user_data['user_input']:
update.message.reply_text("Hey {}".format(user_data['user_input']))
else:
update.message.reply_text("Where is bob?!")
return CHECK_INPUT
The Done method will clean up the conversation
def done(update, context):
markup = get_markup(context)
update.message.reply_text("Bye")
return ConversationHandler.END
Ok that escalated quickly... I rewrote that code from my own working version of a conversation handler, please check for bugs :) Maybe the user_data has to be cleared in the Done method.