I would like to get the New Messages from a specific channel.
I have tried the following until now:
from telethon import TelegramClient, events
api_id = 242...
api_hash = '8a06ca620417c9964a058e0dc...'
bot_token = '1474729480:AAEhUPmVX_m...'
channelId = '-36744...'
client = TelegramClient('bot', api_id, api_hash).start(bot_token=bot_token)
client.start()
#client.on(events.NewMessage(channelId))
async def main(event):
me = client.get_me()
print(me.stringify())
print(event.stringify())
client.run_until_disconnected()
Unfortunately, it did not work.
Does anyone know why? Did I miss something?
Greetings
Please use this:
chats = [channelId]
from telethon import TelegramClient, events
api_id = 242...
api_hash = '8a06ca620417c9964a058e0dc...'
bot_token = '1474729480:AAEhUPmVX_m...'
channelId = '-36744...'
client = TelegramClient('bot', api_id, api_hash).start(bot_token=bot_token)
client.start()
#client.on(events.NewMessage(chats = [channelId]))
async def main(event):
me = client.get_me()
print(me.stringify())
print(event.stringify())
client.run_until_disconnected()
Related
I tried to write a Discord bot that forwards messages from one server to another. But I get a warning that disconnects my connection to the discord gateway. I read that it is possible because of tyme.slep(), but without it, the connection is always interrupted. As I understand it, DDOS protection is activated due to a large number of requests.
import asyncio
import websocket
import json
from threading import Thread
import discord
import requests
from io import BytesIO
import time
from discord.ext import tasks
# Bot
bot_token = "anything"
user_token = "anything"
client = discord.Client(intents=discord.Intents.default())
# Channels list
f = open('channels.txt', 'r')
channels_file = f.read()
channels_array = channels_file.strip().split('\n')
# Connect func
def send_json_request(ws, request):
ws.send(json.dumps(request))
def receive_json_response(ws):
response = ws.recv()
if response:
return json.loads(response)
#WebSoket
def on_closed(ws):
ws.connect("wss://gateway.discord.gg/?v=6&encording=json")
ws = websocket.WebSocket(on_close=on_closed)
ws.connect("wss://gateway.discord.gg/?v=6&encording=json")
def receive_json_response(ws):
response = ws.recv()
if response:
return json.loads(response)
def get_attachment_media(media):
media_array = []
for i in media:
response = requests.get(i['url'])
im = BytesIO(response.content)
print(im)
media_array.append(discord.File(im))
return media_array
def get_channel(id):
for i in channels_array:
if i == id:
return True
return False
#Heartbeat
def heartbeat(interval):
print("Heartbeat begin")
while True:
time.sleep(interval)
heartbeatJSON = {
"op": 1,
"d": "null"
}
send_json_request(ws, heartbeatJSON)
print("Heartbeat sent")
#tasks.loop(seconds=0.5)
async def main():
channel = client.get_channel(anything)
event = receive_json_response(ws)
try:
if event['d']['author']['id'] == 'anything':
return
id_channel = event['d']['channel_id']
id_guild = event['d']['guild_id']
if get_channel(id_channel):
content = event['d']['content']
attachment_media = get_attachment_media(event['d']['attachments'])
await channel.send(content, files=attachment_media)
op_code = event('op')
if op_code == 11:
print('Heartbeat recieved')
except:
pass
#client.event
async def on_ready():
event = receive_json_response(ws)
heartbeat_interval = event['d']['heartbeat_interval'] / 1000
send_json_request(ws, {
"op": 2,
"d": {
"token": user_token,
"properties": {
"$os": 'linux',
"$browser": 'chrome',
"$device": 'pc'
}
}
})
main.start()
asyncio.run(heartbeat(heartbeat_interval))
client.run(bot_token)
I recommend you to check this answer and adjust it to your code.
However, if you are just trying to make your bot copy the contenet of the messages sent in one server and sending to another one, you can do it in a easier way using the on_message() event. This is the entire code, which should also prevent any warning (unless the bot tries to send too many messages in a short period of time):
import discord
intents = discord.Intents.default()
intents.message_content = True # You are missing the message_content intent! (needed to read the content of the guild's messages)
client = discord.Client(intents=intents)
TOKEN = "Your Token"
guild_id = 123456789 # The guild you want your bot to send the messages to
channel_id = 987654321 # The channel of the guild you want your bot to send the messages to
guild = None
channel = None
#client.event
async def on_ready():
global guild, channel, guild_id, channel_id
await client.wait_until_ready()
guild = client.get_guild(guild_id)
channel = guild.get_channel(channel_id)
print("Logged")
#client.event
async def on_message(message : discord.Message):
if message.author == client.user: # You don't want to send the own bot messages
return
if message.guild.id == guild_id: # You don't want to send the messages from the own guild your bot is sending the messages to
return
await channel.send(f"{message.author}: {message.content}") # Add attachments if you want
client.run(TOKEN)
I am using following code for scrapping messages from a telegram group but getting error;
Please guide me how to solve this or suggest any-other efficient solution.
RuntimeError: You must use "async with" if the event loop is running (i.e. you are inside an "async def")
Code:
from telethon.sync import TelegramClient
import datetime
import pandas as pd
import configparser
config = configparser.ConfigParser()
config.read("telethon.config")
api_id = config["telethon_credentials"]["api_id"]
api_hash = config["telethon_credentials"]["api_hash"]
chats = ['cryptodubai7']
client = TelegramClient('test', api_id, api_hash)
df = pd.DataFrame()
for chat in chats:
with TelegramClient('test', api_id, api_hash) as client:
for message in client.iter_messages(chat, offset_date=datetime.date.today() , reverse=True):
print(message)
data = { "group" : chat, "sender" : message.sender_id, "text" : message.text, "date" : message.date}
temp_df = pd.DataFrame(data, index=[1])
df = df.append(temp_df)
df['date'] = df['date'].dt.tz_localize(None)
You are creating 2 TelegramClient's, doesn't seem needed
You need to client.start()
Like the error suggest, you need to use async
Also an await is needed for retrieving the messages
I'd recommend using an event loop, like asyncio
Something like this should get you in the right direction:
Untested!
from telethon.sync import TelegramClient
import datetime
import pandas as pd
import asyncio
import configparser
config = configparser.ConfigParser()
config.read("telethon.config")
api_id = config["telethon_credentials"]["api_id"]
api_hash = config["telethon_credentials"]["api_hash"]
chats = ['cryptodubai7']
client = TelegramClient('test', api_id, api_hash)
client.start()
async def main():
df = pd.DataFrame()
for chat in chats:
messages = await client.iter_messages(chat, offset_date=datetime.date.today() , reverse=True)
for message in messages:
print(message)
data = { "group" : chat, "sender" : message.sender_id, "text" : message.text, "date" : message.date}
temp_df = pd.DataFrame(data, index=[1])
df = df.append(temp_df)
df['date'] = df['date'].dt.tz_localize(None)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
I am new to both Python and Stack Exchange. When using this code, I receive the error, "Using variable 'status' before assignment [30,96]." It says that the variable status is unassigned in the await command in the loop, even though I assigned it above. If anyone could solve this, I would appreciate it. If any other info is needed, just ask and I can reply with it. Thanks.
import requests
from discord.ext import commands
from discord.ext import tasks
from itertools import cycle
client = commands.Bot(command_prefix = '.')
status = cycle(['Starting.', 'Starting..'])
serverOnePlayerCount = 0
serverTwoPlayerCount = 0
serverOneOnline = 'Offline'
serverTwoOnline = 'Offline'
#client.event
async def on_ready():
change_status.start()
print('Bot is ready.')
#client.command()
async def ping(ctx):
await ctx.send(f'Pong! {round(client.latency * 1000)}ms')
#tasks.loop(seconds=5)
async def change_status():
await client.change_presence(status=discord.Status.online, activity=discord.Game(name=next(status), type=3))
r1 = requests.get('https://api.minehut.com/server/5f0de3303c826f0051e583b1/')
json_data_1 = r1.json()
serverOneOnline = str(json_data_1["server"]["online"])
serverOnePlayerCount = str(json_data_1["server"]["playerCount"])
serverOneStatusMessage = 'Minecraft ----- Server 1 is {} ({}/10 players)'.format(serverOneOnline, serverOnePlayerCount)
r2 = requests.get('https://api.minehut.com/server/5f8242b2d74dc1006100293b/')
json_data_2 = r2.json()
serverTwoOnline = str(json_data_2["server"]["online"])
serverTwoPlayerCount = str(json_data_2["server"]["playerCount"])
serverTwoStatusMessage = 'Minecraft ----- Server 2 is {} ({}/10 players)'.format(serverTwoOnline, serverTwoPlayerCount)
status = cycle([serverOneStatusMessage, serverTwoStatusMessage])
client.run('token')
I am making a discord.Client. I have a DM command that sends a DM to a specific user, but no message is sent to the user when the command is run, but a message is sent on the Context.channel.
Here is my code:
import discord, asyncio
app = discord.Client()
#app.event
async def on_message(message):
if message.content.startswith('!DM'):
usernotsending = []
content = message.content
msg = await message.channel.send('메시지를 보내고 있습니다!')
i = app.user
# 봇의 모든 유저를 for문으로 적용
for i in app.user:
try:
if i == app.user:
return
# 해당 유저의 DM을 염
await i.create_dm()
# 내용전송
await app.dmchannel.send(content)
# DiscordAPI 에서 오류가 발생했을경우
except discord.HTTPException:
# DM을 보내지 못한 유저 태그 list에 저장
usernotsending.append(f'{i.name}#{i.discriminator}')
messageing = """
아래 유저들에게 메시지를 전송하지 못했습니다!
직접 보내주시거나, 따로 전달을 해드려야됩니다!
"""
for msg in usernotsending:
# message 에 유저 태그 추가
messageing += msg
# 메시지 전송
await msg.edit(content=messageing)
Context is only part of a commands.Bot instance. Your code and your explanation don't seem to match. Assuming you want to DM the author:
import discord
app = discord.Client()
#app.event
async def on_message(message):
if message.content.startswith('!DM'):
try:
await message.author.send(...)
except discord.HTTPException:
...
If you want to DM everyone the bot can see:
import discord
app = discord.Client()
#app.event
async def on_message(message):
if message.content.startswith('!DM'):
for user in app.users:
try:
await user.send(...)
except discord.HTTPException:
...
Help: Relatively new to telethon and was having issue with delete_messages()function. It "seems" to do nothing for me...
Initially I am getting the message id from send_message, from the return object's id value. It returns values like 1, 2, etc. Not sure this is the message id though.
I send it to delete_messages as delete_messages(channel, [id])
I get the channel (It's a private channel) from:
def resolve_channel_id(self, name):
try:
if name in self.__channel_ids:
return self.__channel_ids[name]
channel_id = self.client(ResolveUsernameRequest(name))
self.__channel_ids[name] = channel_id
return channel_id
# except UserNameNotOccupiedError as err:
except Exception as err:
# try for private channel
chatinvite = self.client(CheckChatInviteRequest(name))
channel_id = chatinvite.chat.id
access_hash_channel = chatinvite.chat.access_hash
channel_id = InputChannel(channel_id, access_hash_channel)
self.__channel_ids[name] = channel_id
return channel_id
I hope this example is useful for friends :
by this code, if a message with a Hello text is sent to a group with ID -1001300989487, that text will be deleted.
import logging
from telethon import TelegramClient, events
logging.basicConfig(level=logging.INFO)
api_id = XXXXXX
api_hash = 'XXXXXXXXXXXXXXXXXXXXXXX'
phone_number = '+989XXXXXXXX'
################################################
client = TelegramClient('session_name',
api_id,
api_hash,
)
#client.on(events.NewMessage(chats=(-1001300989487)))
async def my_event_handler(event):
if 'hello' in event.raw_text:
await event.delete()
client.start()
client.run_until_disconnected()
print('finish')
Works by updating to latest telethon: 1.0.3, and following documentation... https://telethon.readthedocs.io/en/latest/extra/basic/asyncio-magic.html