Microsoft Teams Python Botbuilder Proactive Messaging - python

What was simple in Webex now seems fairly complicated in the Microsoft world.
What I specifically am looking to do is:
Create a bot in the Azure Bot Framework (Done)
Identify recipient ids using the botbuilder sdk using the recipient email
Use Botframework-Connector to individually identify these recipients, create new conversations, and proactively message them
This is what I have been using so far
https://pypi.org/project/botframework-connector/
from botbuilder.schema import *
from botframework.connector import ConnectorClient
from botframework.connector.auth import MicrosoftAppCredentials
APP_ID = 'azure_bot_app_id'
APP_PASSWORD = 'azure_bot_app_password'
SERVICE_URL = 'azure_bot_messaging_endpoint'
CHANNEL_ID = 'msteams'
BOT_ID = 'azure_bot_subscription_id'
RECIPIENT_ID = 'msteams_individual_user_id'
credentials = MicrosoftAppCredentials(APP_ID, APP_PASSWORD)
connector = ConnectorClient(credentials, base_url=SERVICE_URL)
conversation = connector.conversations.create_conversation(ConversationParameters(
bot=ChannelAccount(id=BOT_ID),
members=[ChannelAccount(id=RECIPIENT_ID)]))
connector.conversations.send_to_conversation(conversation.id, Activity(
type=ActivityTypes.message,
channel_id=CHANNEL_ID,
recipient=ChannelAccount(id=RECIPIENT_ID),
from_property=ChannelAccount(id=BOT_ID),
text='Hello Person!'))
Is this even close to the right approach?

This was the easiest way I found to make it work.
from config import DefaultConfig
from botframework.connector.connector_client import ConnectorClient
from botframework.connector.models import ConversationParameters
from botframework.connector.auth.microsoft_app_credentials import MicrosoftAppCredentials
from botbuilder.core import MessageFactory
from botbuilder.schema import ChannelAccount
CONFIG = DefaultConfig()
recipient_id = <<RECIPIENT_ID>>
to = ChannelAccount(id=recipient_id)
bot_channel = ChannelAccount(id='msteams')
MicrosoftAppCredentials.trust_service_url(CONFIG.SERVICE_URL)
credentials = MicrosoftAppCredentials(CONFIG.APP_ID, CONFIG.APP_PASSWORD)
conn_client = ConnectorClient(credentials, CONFIG.SERVICE_URL)
message_activity = MessageFactory.text(f"Personal message from the Bot!");
conversation_params = ConversationParameters(members=[to], channel_data={ 'tenant': { 'id': CONFIG.TENANT_ID } })
conversation = conn_client.conversations.create_conversation(conversation_params)
conn_client.conversations.send_to_conversation(conversation.id, message_activity)
It is easy to infer all the uppercase variables.
The <<RECIPIENT_ID>> is the MS Teams ID of the user you want to send the message.
Hope this helps.
MSFT does not provide good examples in Python.

With a cursory glance it looks ok (I don't work in Python so can't actually run the example). One thing that does look missing in the TrustServiceUrl call. See here for details.

Related

How do I create invites with usage limit to a private channel on Telegram with Telethon?

I'm using Telethon to create a Telegram BOT and I needed to automate a task of generating a one time use invite
I tried searching about it but didn't find anything at their docs neither stackoverflow (i did find somethings about invites with this library but didn't understood how to handle my situation)
Anything that may help me with this is welcome!!
Thank you in advance!
From telethon.dev, You can mod the example like:
from telethon.sync import TelegramClient
from telethon import functions, types
session_file_name = "" # TODO: session file name without extension
api_id = "" # TODO: api id
api_hash = "" # TODO: api hash
channel_id = -1001109500936 # TODO: channel ID
with TelegramClient(session_file_name, api_id, api_hash) as client:
result = client(functions.messages.ExportChatInviteRequest(
peer=client.get_input_entity(channel_id),
legacy_revoke_permanent=True,
expire_date=None, # Set expiry date if needed like datetime.datetime(2018, 6, 25),
usage_limit=1 # Only one person can use your invite link
))
print(result.stringify())

How to send Properties details in EventHub message using python?

I am referring to this article "https://learn.microsoft.com/en-us/azure/event-hubs/event-hubs-python-get-started-send" related to sending messages to EventHub using Python.
A Message has the following components: offset, body, systemProperties, properties.
offset is auto-generated but we can provide the other.
For my project - apart from message body I also need to send "Properties" which is not part of Body, How to do that? I checked the class EventData(object): and looks like application_properties can be used to do this but i'm not sure how to implement this.
Is application_properties right analogy to obtain "Properties" in message?
Could you please add more details to the article with example displaying how to use the python EventData class for sending detailed information apart from message body like Properties and SystemProperties. As of now Properties is being sent as empty list.
Sample message format that i need to send to EventHub using Python:
Sender.send(EventData('{"**offset**":"2415248","**body**":"TESTone:100,
Temperature:553.0","**systemProperties**":[{"key":{"string":"x-opt-
sequence-number"},"value":{"string":"23512"}},{"key":{"string":"x-opt-
offset"},"value":{"string":"2415248"}},{"key":{"string":"x-opt-
enqueued-time"},"value":{"string":"Fri Feb 22 02:14:23 UTC
2019"}}],"**properties**":[]}'))
And I want to send this dict values in properties: {"key":{"string":"Type"},"value":{"string":"iPhone"}}
I asked this question elsewhere as the solution provided by PraveenS does not actually solve the problem. The correct answer which I received is below, sharing to help others:
The solution is to assign the properties you want to be sent with the message to EventData.properties, applying that to the above code would look like this:
from azure.eventhub import EventHubClient, Receiver, Offset, Sender, EventData
from uamqp import Message
ADDRESS = "amqps://<>.windows.net/<>"
USER = "RootManageSharedAccessKey"
KEY = "<>"
client = EventHubClient(ADDRESS, debug=True, username=USER, password=KEY)
Sender = client.add_sender(partition="0")
client.run()
event = EventData(body="TESTTWO:100, Temperature:-127.0")
### THIS IS WHERE THE CHANGE IS ###
event.properties = {"Type": "iPhone"}
Sender.send(event)
Found solution to this, yes we can use "application_properties" to send "properties" of message.
This is my sample code that worked:
from azure.eventhub import EventHubClient, Receiver, Offset, Sender, EventData
from uamqp import Message
ADDRESS = "amqps://<>.windows.net/<>"
USER = "RootManageSharedAccessKey"
KEY = "<>"
client = EventHubClient(ADDRESS, debug=True, username=USER, password=KEY)
Sender = client.add_sender(partition="0")
client.run()
event = EventData(body="TESTTWO:100, Temperature:-127.0")
event.application_properties = {"Type": "iPhone"}
Sender.send(event)
You may also find useful the following way, which basically do the same:
props = {"Type": "iPhone"} # properties you want to send
columns = ['body', 'properties']
values = [(write_binneddata, props)] # You can also send multiple messages adding tuples to the list
df = spark.createDataFrame(values, columns)
conn_string = f"Endpoint=sb://{event_hub_namespace}.servicebus.windows.net/;SharedAccessKeyName={shared_acc_keyname};SharedAccessKey={shared_acc_key};EntityPath={event_hub_name}"
conf = { 'eventhubs.connectionString' : conn_string }
ds = (
df
.write
.format("eventhubs")
.options(**conf)
.option("checkpointLocation", f"{checkpoint_path}")
.save()
)
PS: it needs this library installed.

Creating and sending vCard files via MMS

I'm trying to send vCard files (which allow you to save contacts on mobile devices) using Twilio's API and vobject.
Here's my code:
import vobject
import requests
from twilio.rest import Client
account_sid = 'MY_SID_HIDDEN'
auth_token = 'AUTH_TOKEN_HIDDEN'
j = vobject.vCard()
j.add('n')
j.n.value = vobject.vcard.Name(family='Harris', given='Jeffrey')
j.add('fn')
j.fn.value = 'Jeffrey Harris'
j.add('email')
j.email.value = 'jeffrey#osafoundation.org'
j.email.type_param = 'Internet'
client = Client(account_sid, auth_token)
client.api.account.messages.create(
to="NUMBER_HIDDEN",
from_="NUMBER_HIDDEN",
body=j
)
When my device receives the message, it looks like this:
<VCARD| [<EMAIL{'TYPE': ['Internet']}jeffrey#osafoundation.org>, <FN{}Jeffrey Harris>, <N{} Jeffrey  Harris >]>
Why is this happening?
I understand what you want to do, but there are a couple issues.
Vcards are files; you have put marked up text in a text field (body).
For attaching files using the API, you point it at a URL that the Twilio Server can access and make sure you properly declare your mime-type encoding in the API and on server where the card will be stored.
Note: I'm not sure if the mime-type is required anymore, as they don't use it on this example for a attaching picture (https://www.twilio.com/docs/api/messaging/send-messages#send-a-message-with-an-image-url ; change the language to python).
You would attach the file (vcard) using mediaUrl.
ex// mediaUrl=https://qrstuff.com/vcard.download/dec91a6d6/yo_yo_ma_vCard.vcf

How can I download the chat history of a group in Telegram?

I would like to download the chat history (all messages) that were posted in a public group on Telegram. How can I do this with python?
I've found this method in the API https://core.telegram.org/method/messages.getHistory which I think looks like what I'm trying to do. But how do I actually call it? It seems there's no python examples for the MTproto protocol they use.
I also looked at the Bot API, but it doesn't seem to have a method to download messages.
You can use Telethon. Telegram API is fairly complicated and with the telethon, you can start using telegram API in a very short time without any pre-knowledge about the API.
pip install telethon
Then register your app (taken from telethon):
the link is: https://my.telegram.org/
Then to obtain message history of a group (assuming you have the group id):
chat_id = YOUR_CHAT_ID
api_id=YOUR_API_ID
api_hash = 'YOUR_API_HASH'
from telethon import TelegramClient
from telethon.tl.types.input_peer_chat import InputPeerChat
client = TelegramClient('session_id', api_id=api_id, api_hash=api_hash)
client.connect()
chat = InputPeerChat(chat_id)
total_count, messages, senders = client.get_message_history(
chat, limit=10)
for msg in reversed(messages):
# Format the message content
if getattr(msg, 'media', None):
content = '<{}> {}'.format( # The media may or may not have a caption
msg.media.__class__.__name__,
getattr(msg.media, 'caption', ''))
elif hasattr(msg, 'message'):
content = msg.message
elif hasattr(msg, 'action'):
content = str(msg.action)
else:
# Unknown message, simply print its class name
content = msg.__class__.__name__
text = '[{}:{}] (ID={}) {}: {} type: {}'.format(
msg.date.hour, msg.date.minute, msg.id, "no name",
content)
print (text)
The example is taken and simplified from telethon example.
With an update (August 2018) now Telegram Desktop application supports saving chat history very conveniently.
You can store it as json or html formatted.
To use this feature, make sure you have the latest version of Telegram Desktop installed on your computer, then click Settings > Export Telegram data.
https://telegram.org/blog/export-and-more
The currently accepted answer is for very old versions of Telethon. With Telethon 1.0, the code can and should be simplified to the following:
# chat can be:
# * int id (-12345)
# * str username (#chat)
# * str phone number (+12 3456)
# * Peer (types.PeerChat(12345))
# * InputPeer (types.InputPeerChat(12345))
# * Chat object (types.Chat)
# * ...and many more types
chat = ...
api_id = ...
api_hash = ...
from telethon.sync import TelegramClient
client = TelegramClient('session_id', api_id, api_hash)
with client:
# 10 is the limit on how many messages to fetch. Remove or change for more.
for msg in client.iter_messages(chat, 10):
print(msg.sender.first_name, ':', msg.text)
Applying any formatting is still possible but hasattr is no longer needed. if msg.media for example would be enough to check if the message has media.
A note, if you're using Jupyter, you need to use async directly:
from telethon import TelegramClient
client = TelegramClient('session_id', api_id, api_hash)
# Note `async with` and `async for`
async with client:
async for msg in client.iter_messages(chat, 10):
print(msg.sender.first_name, ':', msg.text)
Now, you can use TDesktop to export chats.
Here is the blog post about Aug 2018 update.
Original Answer:
Telegram MTProto is hard to use to newbies, so I recommend telegram-cli.
You can use third-party tg-export script, but still not easy to newbies too.
You can use the Telethon library. for this you need to register your app and connect your client code to it (look at this).
Then to obtain message history of a entry (such as channel, group or chat):
from telethon.sync import TelegramClient
from telethon.errors import SessionPasswordNeededError
client = TelegramClient(username, api_id, api_hash, proxy=("socks5", proxy_ip, proxy_port)) # if in your country telegram is banned, you can use the proxy, otherwise remove it.
client.start()
# for login
if not client.is_user_authorized():
client.send_code_request(phone)
try:
client.sign_in(phone, input('Enter the code: '))
except SessionPasswordNeededError:
client.sign_in(password=input('Password: '))
async for message in client.iter_messages(chat_id, wait_time=0):
messages.append(Message(message))
# write your code

schedule email with sendgrid python

I am using python module of sendgrid (https://github.com/sendgrid/sendgrid-python) to send transactional emails. I need help with the syntax to send the email at a scheduled time.
The general sendgrid documentation asks to modify json as "{ “send_at”: 1409348513 }". I believe this json is not directly accessible in sendgrid-python. I need syntax for doing equivalent thing with the python library.
My current code is equivalent to the one copied below. It would be great if some one can suggest how to modify this code to schedule it at a particular time e.g. datetime.dateime.now() + datetime.timedelta(days=1)
import sendgrid
from sendgrid.helpers.mail import Email, Content, Substitution, Mail
import urllib2 as urllib
def send_email_custom():
sg = sendgrid.SendGridAPIClient(apikey=myApiKey)
from_email = Email(sendEmail)
to_email = Email(custEmail)
reply_to_email = Email(receiveEmail)
content = Content("text/html", "Introduction")
mail = Mail(from_email, subject="Hi!", to_email=to_email, content=content)
mail.personalizations[0].add_substitution(Substitution("_firstName_", firstName))
mail.set_template_id(templateId)
try:
response = sg.client.mail.send.post(request_body=mail.get())
except urllib.HTTPError as e:
print(e.read())
return False
if response.status_code >=200 and response.status_code < 300:
return True
else:
return False
send_at is a component of the personalizations Object, so you can define it at that level, allowing you to set distinct sending times for each recipient/personalization set.
If you don't need that, you can also set it at the top mail level.
Looks like you should be able to do that by following this example. You can specify all of the raw fields you need.
Exact code solution:
mail = Mail(from_email, subject="Hi!", to_email=to_email, content=content)
mail.send_at = SendAt(1461775053) # Time is specified in UNIX form.
# This takes advantage of Sendgrid's inbuilt email scheduler
# but you can't schedule more than 72 hours in advance.
This removes the need to deal with personalizations for send time.
Source: line 308 of https://github.com/sendgrid/sendgrid-python/blob/main/examples/helpers/mail_example.py
Posting this for those who Googled their way here in 2022 or later.

Categories