i'm learning Python!
I'm building a Bot that searches for products in an e-commerce, the bot will always send a message with a price predefined by me!
The bot does a new search every 5 minutes, but I don't want send the same product again in the next message, i did some research but found nothing that fits what i need.
Sorry for my bad english! I hope you understand what I meant.
Code:
def send_to_telegram(message):
apiToken = 'xxxxx'
chatID = '-xxxx'
bot = telebot.TeleBot(apiToken)
if placa and fabricante_1 in marca:
bot.send_message(
chat_id=chatID, text=f"<b>Modelo:</b> {marca} \n<b>Fabricante:</b> {fabricante_1}\n<b>Preço a vista:</b> R$ {valor_preco_avista} \n<b>Preço a prazo:</b> R$ {valor_preco_prazo} \n<b>Loja:</b> {loja} \n\n<b>Link Produto:</b> {url_completa}", parse_mode='HTML')
I tried some modules like: schedule, time
But in the end the bot sends the duplicate message anyway.
I managed to solve my problem, I'll leave the solution for anyone who has a similar doubt in the future!
To avoid sending repeated messages with a Telegram bot with Python, you can store a record of the messages that have already been sent and check against this record before sending a new message.
import os
import pickle
sent_messages_file = "sent_messages.pickle"
if os.path.exists(sent_messages_file):
with open(sent_messages_file, "rb") as f:
sent_messages = pickle.load(f)
else:
sent_messages = []
def send_message(mensagem):
apiToken = 'XXXXXXXXXX'
chatID = 'XXXXXXXX'
bot = telebot.TeleBot(apiToken)
bot.send_message(
chat_id=chatID, text=message, parse_mode='HTML')
sent_messages.append(message)
with open(sent_messages_file, "wb") as f:
pickle.dump(sent_messages, f)
In this code, the sent_messages list is saved to a file using the pickle module. Before sending a new message, the code checks if the sent_messages_file exists. If it exists, the code loads the sent_messages list from the file. If it does not exist, the code creates an empty sent_messages list. After sending a message, the code saves the updated sent_messages list to the file.
This way, when you run the code again, it will load the sent_messages list from the file, and only send new messages that have not been sent before.
Related
Basically I have a discord bot that auto leaves servers unless its in a database. I was wondering how I could make a command to add to that database and remove? Heres my current code
server=[878537556332015626,
884958773913985054,
869615568838357052]
#client.event
async def on_guild_join(guild):
if guild.id in server:
pass
elif guild.id not in server:
await guild.leave()
So where it says "server=[stuff here]" how could i make a command to add servers ids to that database? Maybe like ';addserver server-id' and it'd add it to that database, and also a remove command. Like ';removeserver server-id' ive attempted multiple times but it didnt work, neither did it show an error.
Or help me make this into a json file!
If your goal is to make a command for your bot such as ;addserver server-id, it would be quite simple. Here's an example for checking the validity of the ID and writing it to a servers.json file if it's valid:
#client.command()
async def addserver(ctx, message = None):
if client.get_guild(int(message)): # If the bot is in a guild with this ID, returns True
serverFile = json.loads(open('servers.json', 'r').read()) # Reading Json file to a dict
serverFile['servers'].append(int(message)) # Appending new ID to the dict
with open('servers.json', 'w') as writeFile:
json.dump(serverFile, writeFile, indent=4) # Writing dict to Json file
else:
pass # Do whatever you want with this part, maybe an error message would be sent to the command sender or something.
And servers.json should be laid out like this:
{
"servers": [
]
}
Reading the list of server IDs from the file would look like this:
json.loads(open('servers.json', 'r').read())['servers'] # Returns a list of IDs in the file.
And to remove an ID from the list:
#client.command()
async def removeserver(ctx, message = None):
serverList = json.loads(open('servers.json', 'r').read())['servers']
for id in serverList:
if int(message) == id:
serverList.remove(id)
serverDict = {}
serverDict['servers'] = serverList
with open('servers.json', 'w') as writeFile:
json.dump(serverDict, writeFile, indent=4)
The part you'll likely find the most value out of is the if client.get_guild(int(message)) line, as it will let you know whether the ID is valid or not. This can be applied to new functions that could clean up your server list if need be.
I have a problem sending proactive messages using the Bot Framework with Python.
First what I need is to get the message body from Outlook, and then the bot must send that as a message to all the chats where it was added.
To do that, first I created a new file and called it Email.py.
To read every incoming message body I simply used while true: and time.sleep()
Here is my code example:
import imaplib, email, getpass
from email import policy
import json
import time
imap_host = 'outlook.office365.com'
imap_user = 'xx#xx.com'
# init imap connection
mail = imaplib.IMAP4_SSL(imap_host, 993)
rc, resp = mail.login(imap_user, 'xxxxxx')
while True:
# select only unread messages from inbox
mail.select('Inbox')
status, data = mail.search(None, '(UNSEEN)')
if not data[0].split():
time.sleep(120)
# Bot message variable
Message_for_bot = ''
# for each e-mail messages
for num in data[0].split():
# get a single message and parse it by policy.SMTP (RFC compliant)
status, data = mail.fetch(num, '(RFC822)')
email_msg = data[0][1]
email_msg = email.message_from_bytes(email_msg, policy=policy.SMTP)
# print only message parts that contain text data
for part in email_msg.walk():
if part.get_content_type() == "text/plain":
for line in part.get_content().splitlines():
Message_for_bot += '\n' + line
print(Message_for_bot)
After I successfully created a program to read and print all incoming messages, I tried to build my bot. I found a proactive message bot on the Internet and used it as an example.
First I thought to just run this file with os in the background, but then my bot wasn't running. So then I tried adding an async function in the bot file but it didn't work. My bot just ignores that function. (Then I found the async functions in activity_handler.py, but I didn't find any that could help me.)
Then I tried adding an on_message_activity function and thought maybe it will start working if I call the bot like "#bot hi" for example in Teams. For that idea I must always run the while cycle and never stop the bot, but then I just get a message, and if there's a new incoming message then the bot doesn't write it anymore, and it's not a solution because if the bot is used for multiple chats then it simply doesn't work this way.
Then I try include my code on on_members_added_activity it seems working on azure test in web chat perfectly, but in teams after 1-2 messages stopping to work.
my code
async def on_members_added_activity(
self, members_added: [ChannelAccount], turn_context: TurnContext
):
imap_host = 'outlook.office365.com'
imap_user = 'xxxxxx#xxxxxx.com'
# init imap connection
mail = imaplib.IMAP4_SSL(imap_host, 993)
rc, resp = mail.login(imap_user, 'xxxxxx')
while True:
# select only unread messages from inbox
mail.select('Inbox')
status, data = mail.search(None, '(UNSEEN)')
if not data[0].split():
time.sleep(5)
# Bot message variable
Message_for_bot = ''
# for each e-mail messages
for num in data[0].split():
# get a single message and parse it by policy.SMTP (RFC compliant)
status, data = mail.fetch(num, '(RFC822)')
email_msg = data[0][1]
email_msg = email.message_from_bytes(email_msg, policy=policy.SMTP)
# print only message parts that contain text data
for part in email_msg.walk():
if part.get_content_type() == "text/plain":
for line in part.get_content().splitlines():
Message_for_bot += '\n' + line
await turn_context.send_activity(f"{Message_for_bot}")
for member in members_added:
if member.id != turn_context.activity.recipient.id:
await turn_context.send_activity(
"bot starting work..."
)
So maybe it's possible to send a message to wherever the bot is added (it needs to get this information somehow, maybe it's kept in the bot memory) whenever Message_for_bot is not empty.
All help will be appreciated.
As we have discussed some logic has to change
Move your code out of the on_members_added_activity function
Use Proactive concept to send the message
-Vinoth
I am creating a reference bot for chatting in VK in Python using the Callback Api. The bot works correctly if you write to the group messages. However, if you write to a conversation (to which the bot is added), it replies to private messages. All rights to read, etc. issued. As I understand it (studying information on the internet), I use user_id, not chat_id. But I didn't understand how to fix it correctly (
p.s. It is advisable that the bot write both in private messages and in a conversation, depending on where they ask.
p.p.s perhaps the question seems ridiculous, but I just started to study this area, and I did not find the answer on the net :-)
The bot itself:
import vk
import random
import messageHandler
# app.route ('/', methods = ['POST'])
def processing ():
data = json.loads (request.data)
if 'type' not in data.keys ():
return 'not vk'
if data ['type'] == 'confirmation':
return confirmation_token
elif data ['type'] == 'message_new':
messageHandler.create_answer (data ['object'] ['message'], token)
return 'ok'
"Responder":
import importlib
from command_system import command_list
def load_modules ():
# path from the working directory, it can be changed in the application settings
files = os.listdir ("mysite / commands")
modules = filter (lambda x: x.endswith ('. py'), files)
for m in modules:
importlib.import_module ("commands." + m [0: -3])
def get_answer (body):
# Default message if unrecognizable
message = "Sorry, I don't understand you. Write '/ help' to see my commands."
attachment = ''
for c in command_list:
if body in c.keys:
message, attachment = c.process ()
return message, attachment
def create_answer (data, token):
load_modules ()
user_id = data ['from_id']
message, attachment = get_answer (data ['text']. lower ())
vkapi.send_message (user_id, token, message, attachment)
I don't speak English well, so I apologize for the crooked translation)
Use Peer_id, instead of from_id. (data->object->peer_id)
(i used php, but i had a similar problem. this is the solution)
probably something like this:
def create_answer (data, token):
load_modules ()
user_id = data ['peer_id'] # id source edited
message, attachment = get_answer (data ['text']. lower ())
vkapi.send_message (user_id, token, message, attachment)
from_id - person who sent the message
peer_id - in which dealogue message was received. (for groups it looks like 20000005)
So, you will send the message to conversation (does not matter is this PM or conversation with a lot of people)
I am attempting to create a small dataset by pulling messages/responses from a slack channel I am a part of. I would like to use python to pull the data from the channel however I am having trouble figuring out my api key. I have created an app on slack but I am not sure how to find my api key. I see my client secret, signing secret, and verification token but can't find my api key
Here is a basic example of what I believe I am trying to accomplish:
import slack
sc = slack.SlackClient("api key")
sc.api_call(
"channels.history",
channel="C0XXXXXX"
)
I am willing to just download the data manually if that is possible as well. Any help is greatly appreciated.
messages
See below for is an example code on how to pull messages from a channel in Python.
It uses the official Python Slack library and calls
conversations_history with paging. It will therefore work with
any type of channel and can fetch large amounts of messages if
needed.
The result will be written to a file as JSON array.
You can specify channel and max message to be retrieved
threads
Note that the conversations.history endpoint will not return thread messages. Those have to be retrieved additionaly with one call to conversations.replies for every thread you want to retrieve messages for.
Threads can be identified in the messages for each channel by checking for the threads_ts property in the message. If it exists there is a thread attached to it. See this page for more details on how threads work.
IDs
This script will not replace IDs with names though. If you need that here are some pointers how to implement it:
You need to replace IDs for users, channels, bots, usergroups (if on a paid plan)
You can fetch the lists for users, channels and usergroups from the API with users_list, conversations_list and usergroups_list respectively, bots need to be fetched one by one with bots_info (if needed)
IDs occur in many places in messages:
user top level property
bot_id top level property
as link in any property that allows text, e.g. <#U12345678> for users or <#C1234567> for channels. Those can occur in the top level text property, but also in attachments and blocks.
Example code
import os
import slack
import json
from time import sleep
CHANNEL = "C12345678"
MESSAGES_PER_PAGE = 200
MAX_MESSAGES = 1000
# init web client
client = slack.WebClient(token=os.environ['SLACK_TOKEN'])
# get first page
page = 1
print("Retrieving page {}".format(page))
response = client.conversations_history(
channel=CHANNEL,
limit=MESSAGES_PER_PAGE,
)
assert response["ok"]
messages_all = response['messages']
# get additional pages if below max message and if they are any
while len(messages_all) + MESSAGES_PER_PAGE <= MAX_MESSAGES and response['has_more']:
page += 1
print("Retrieving page {}".format(page))
sleep(1) # need to wait 1 sec before next call due to rate limits
response = client.conversations_history(
channel=CHANNEL,
limit=MESSAGES_PER_PAGE,
cursor=response['response_metadata']['next_cursor']
)
assert response["ok"]
messages = response['messages']
messages_all = messages_all + messages
print(
"Fetched a total of {} messages from channel {}".format(
len(messages_all),
CHANNEL
))
# write the result to a file
with open('messages.json', 'w', encoding='utf-8') as f:
json.dump(
messages_all,
f,
sort_keys=True,
indent=4,
ensure_ascii=False
)
This is using the slack webapi. You would need to install requests package. This should grab all the messages in channel. You need a token which can be grabbed from apps management page. And you can use the getChannels() function. Once you grab all the messages you will need to see who wrote what message you need to do id matching(map ids to usernames) you can use getUsers() functions. Follow this https://api.slack.com/custom-integrations/legacy-tokens to generate a legacy-token if you do not want to use a token from your app.
def getMessages(token, channelId):
print("Getting Messages")
# this function get all the messages from the slack team-search channel
# it will only get all the messages from the team-search channel
slack_url = "https://slack.com/api/conversations.history?token=" + token + "&channel=" + channelId
messages = requests.get(slack_url).json()
return messages
def getChannels(token):
'''
function returns an object containing a object containing all the
channels in a given workspace
'''
channelsURL = "https://slack.com/api/conversations.list?token=%s" % token
channelList = requests.get(channelsURL).json()["channels"] # an array of channels
channels = {}
# putting the channels and their ids into a dictonary
for channel in channelList:
channels[channel["name"]] = channel["id"]
return {"channels": channels}
def getUsers(token):
# this function get a list of users in workplace including bots
users = []
channelsURL = "https://slack.com/api/users.list?token=%s&pretty=1" % token
members = requests.get(channelsURL).json()["members"]
return members
I have sleekXMPP for python and I have used the API to create functions to send messages, although when I researched into receiving them I can't find anything, can someone please help me to work this out, or disprove the possibility. Thanks.
Below is the code I used to send Messages, If its any help.
to = config.get('usermap', to[4:])
gmail_from_user = config.get('auth', 'email')
gmail_from_secret = config.get('auth', 'secret')
sys.stdout = stdouttmp
sys.stderr = stderrtmp
print "Sending chat message to " + to
xmpp = SendMsgBot(gmail_from_user, gmail_from_secret, to, message)
xmpp.register_plugin('xep_0030') # Service Discovery
xmpp.register_plugin('xep_0199') # XMPP Ping
sys.stdout = stdouttmp
if xmpp.connect(('talk.google.com', 5222)):
xmpp.process(block=True)
else:
sys.stdout = stdouttmp
print("Unable to connect.")
sys.stdout = stdouttmp
sys.stderr = stderrtmp
btw I'm using a .cfg text file for the users email and password, along with some contacts, which is then parsed in
I see that you're using the send_client.py example. The intent of that example is how to reliably log in, send a single message, and then log out. Your use case is to both send and receive messages, so you would be better served looking at the echo_client.py example.
Notably, in order to receive a message you would do:
# in your __init__ method:
def __init__(...):
# ...
self.add_event_handler('message', self.recv_message)
def recv_message(self, msg):
# You'll probably want to ignore error and headline messages.
# If you want to handle group chat messages, add 'groupchat' to the list.
if msg['type'] in ('chat', 'normal'):
print "%s says: %s" % (msg['from'], msg['body'])
Again, you will need to switch from using the SendMsgBot example because it automatically disconnects after sending its message.
Don't forget that there is the sleek#conference.jabber.org chat room if you need any help.
-- Lance