is there a way to check if a chat is a group chat? Or at least to find out how many users there are in a group.
Like by checking for the user number, if it is 2, then it is obviously 1-1 (Single), but if it as anything else, it would be a group chat.
The Type property of the chat object will be either chatTypeDialog or chatTypeMultiChat with the latter being a group chat. You can safely ignore the other legacy enumeration values.
This is a slight modification of a code that I wrote for another question here. The following code checks if there are any Group chats in either the open chats or the bookmarked chats. You should pass in a topic to find a chat of that topic.
def checkGroupChat(topic=""):
"""
Checks if a group exists.
"""
import Skype4Py as skype
skypeClient = skype.Skype()
skypeClient.Attach()
for elem in skypeClient.ActiveChats: # Looks in active chats and returns True if chat is found.
if len(elem.Members) > 2 and elem.Topic == topic:
return True
for chat in skypeClient.BookmarkedChats: # Looks in Bookmarked Chats.
if chat.Topic == topic:
return True
return False
This worked for me:
def on_message(message, status):
len(message.Chat.Members) > 2:
# this is a private chat
s = Skype4Py.Skype()
s.OnMessageStatus = on_message
s.Attach()
message.Chat.Type always hanged for me and then after some seconds the connection to Skype is lost. Seems to be a bug
Related
I'm trying to create new invite and then send cancel invite using python iCalendar package. New invite working as expected, but cancel invite is not working, instead its creating duplicate invite.
Invite .ics looks as below, which i'm sending as attachment in email
New invite
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Calendar invite//mxm.dk//
METHOD:REQUEST
BEGIN:VEVENT
SUMMARY:[CONFIRMED]: Python meeting calendar
DTSTART;VALUE=DATE-TIME:20210606T080000
DTEND;VALUE=DATE-TIME:20210606T170000
DTSTAMP;VALUE=DATE-TIME:20210604T165119Z
UID:74cf83e4-e4ff-42dd-97d2-fc5964661e37
SEQUENCE:1622850679
DESCRIPTION:Event1 details
LOCATION:Portland\, Oregon
ORGANIZER;CN="Max Rasmussen";ROLE=CHAIR;SENT-BY="MAILTO:tester-grimsby#tester.com":MAILTO:karthikvadla16#gmail.com
STATUS:CONFIRMED
END:VEVENT
END:VCALENDAR
Cancel invite
I'm making sure to pass below properties as recommended
Same UID of the event
Method: CANCEL
Status: CANCELLED
Organizer: is set.
Sequence: incremented (to set priority)
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Calendar invite//mxm.dk//
METHOD:CANCEL
BEGIN:VEVENT
SUMMARY:[CANCELLED]: Python meeting calendar
DTSTART;VALUE=DATE-TIME:20210606T080000
DTEND;VALUE=DATE-TIME:20210606T170000
DTSTAMP;VALUE=DATE-TIME:20210604T165432Z
UID:74cf83e4-e4ff-42dd-97d2-fc5964661e37
SEQUENCE:1622850872
DESCRIPTION:Event1 details
LOCATION:Portland\, Oregon
ORGANIZER;CN="Max Rasmussen";ROLE=CHAIR;SENT-BY="MAILTO:tester-grimsby#tester.com":MAILTO:karthikvadla16#gmail.com
STATUS:CANCELLED
END:VEVENT
END:VCALENDAR
I tried out all work-arounds as suggested on stackoverflow, still not able to resolve the issue.
Can someone help me, what i'm missing here?
Here is my source code
def create_calendar_invite(calendar_event: dict):
"""Method to build calendar invite"""
calendar = Calendar()
calendar.add("prodid", "-//Grimsby Calendar invite//mxm.dk//")
calendar.add("version", "2.0")
status = calendar_event.get("status")
if status == "CANCELLED":
calendar.add("method", "CANCEL")
else:
calendar.add("method", "REQUEST")
event = __create_calendar_event_object(calendar_event)
calendar.add_component(event)
return calendar.to_ical()
def __create_calendar_event_object(calendar_event):
"""Method to build calendar event object"""
event = Event()
event.add("uid", calendar_event["event_uid"])
# set priority of the event
status = calendar_event.get("status")
if status == "CANCELLED":
event.add("sequence", 1)
else:
event.add("sequence", 0)
# status can be TENTATIVE/CONFIRMED/CANCELLED
# status = calendar_event["status"]
current_timestamp = datetime.now()
# organizer = vCalAddress('MAILTO:karthikvadla16#gmail.com')
# "SENT-BY", for specifying another calendar
# user that is acting on behalf of the "Organizer"
# organizer.params['sent-by'] = vText(f"MAILTO:tester-grimsby#{os.getenv('DOMAIN_NAME')}")
# organizer.params['cn'] = vText('Max Rasmussen')
# organizer.params['role'] = vText('CHAIR')
event.add('organizer', "karthikvadla16#gmail.com")
event.add("status", status)
event.add("summary", f"[{status}]: {calendar_event['summary']}")
event.add("dtstart", datetime.fromtimestamp(calendar_event["start_timestamp"]))
event.add("dtend", datetime.fromtimestamp(calendar_event["end_timestamp"]))
event.add("dtstamp", current_timestamp)
event.add("location", vText(calendar_event["location"]))
event.add("description", vText(calendar_event["description"]))
return event
Getting an application to recognise an update or cancel requires a combination of
Exact SAME UID as original invite.
Incremented SEQUENCE from the last update. IE if there was a modification inbetween then SEQUENCE would be > 1
LAST-MODIFIED https://datatracker.ietf.org/doc/html/rfc5545#section-3.8.7.3
Email recipient must be an ATTENDEE and there must be adequate ATTENDEE details. See Icalendar ICS update not working in google calendar
I'm trying to get my Python Slack bot to automatically reply in a thread if I post it commands in one. However, regardless of where I post my commands - in a thread or otherwise, it still replies as a general message.
I wish to get it to reply in a thread. Here's my code so far (I've truncated most of the initializing and startup code for the sake of brevity):
import os, time, re, inspect, functools
from slackclient import SlackClient
class Bot(object):
def __init__(self, token):
...
def startup(self):
...
def parse_bot_commands(self, slack_events):
"""
Parses a list of events coming from the Slack RTM API to find bot commands.
If a bot command is found, this function returns a tuple of command and channel.
If its not found, then this function returns None, None.
"""
for event in slack_events:
if event["type"] == "message" and not "subtype" in event:
user_id, message = self.parse_direct_mention(event["text"])
if user_id == self.starterbot_id:
return message, event["channel"]
return None, None
def parse_direct_mention(self, message_text):
"""
Finds a direct mention (a mention that is at the beginning) in message text
and returns the user ID which was mentioned. If there is no direct mention, returns None
"""
matches = re.search(self.MENTION_REGEX, message_text)
# the first group contains the username, the second group contains the remaining message
return (matches.group(1), matches.group(2).strip()) if matches else (None, None)
def handle_command(self, command, channel):
"""
Executes bot command if the command is known
"""
# Default response is help text for the user
default_response = "Not sure what you mean. Try *{}*.".format(self.EXAMPLE_COMMAND)
# Finds and executes the given command, filling in response
response = None
# NOTE: This is where you start to implement more commands!
if command.lower().startswith("roll"):
response = 'Rock and Roll!"
# Sends the response back to the channel
self.slack_client.api_call("chat.postMessage", channel=channel, text=response or default_response)
'''START THE BOT!'''
#Initialize the token (when installing the app)
bot = Bot('xxx-xxx')
bot.startup()
Slash commands do not work properly in threads. Its a known issue which has so far not been fixed.
See also this answer: Can a Slack bot get the thread id that a slash command was sent from?
I'm stuck with an error in telethon, when trying to get users data.
First, I get new messages from some groups, it's ok, but when I try to get user data (name, first_name etc) - sometimes it's ok, but mostly fails with error
ValueError: Could not find the input entity for "12345678".
Please read https://telethon.readthedocs.io/en/latest/extra/basic/entities.html
to find out more details.
I read that article a lot of times, tried to use also client.get_input_entity as it says, but it doesn't help
Here is my code:
import logging
from telethon import TelegramClient, events
logging.basicConfig(level=logging.WARNING)
logging.getLogger('asyncio').setLevel(logging.ERROR)
entity = 'session' # session
api_id = 123456
api_hash = 'hash'
phone = '1234567'
chats = ['group1', 'group2', 'group3']
client = TelegramClient(entity, api_id, api_hash)
#client.on(events.NewMessage(chats=chats))
async def normal_handler(event):
print(event.message.message)
print(event.date)
print(event.from_id)
print(event.message.to_id)
#user = await client.get_input_entity(event.from_id)
user = await client.get_entity(event.from_id)
client.start()
client.run_until_disconnected()
How can I fix that?
And one more question, how can I retrieve info about group?
I know it's id from event.message.to_id, but can't get how to get it's name.
The docs for the library looks not very friendly for beginners. =(
Thank you
Telegram does not allow to get user profile by integer id if current client had never "saw" it.
Telethon documentation (https://telethon.readthedocs.io/en/latest/extra/basic/entities.html) suggests following options to make contact "seen":
if you have open conversation: use client.get_dialogs()
if you are in same group: use client.get_participants('groupname')
if you are it was forward in group: use client.get_messages('groupname', 100)
Choose which one is applicable in your case. One of them will make contact "seen", and it will be possible to use client.get_entity(event.from_id)
I've little question about Django Channels, WebSockets, and chat applications. Serving with google gets me to chatrooms, where people can connect and start a chat. But I don't know how one user can send another user instant message.
For example:
1) I add John to friends, and want to start chat.
2) On server side I can generate object Room, with me and John as members.
3) When I send message via WebSocket to this room, I know for who this message is, but I don't know how to get John's channel
#channel_session_user_from_http
def ws_connect(message):
rooms_with_user = Room.objects.filter(members=message.user)
for r in rooms_with_user:
Group('%s' % r.name).add(message.reply_channel)
#channel_session_user
def ws_receive(message):
prefix, label = message['path'].strip('/').split('/')
try:
room = Room.objects.get(name=label)
except Exception, e:
room = Room.objects.create(name=get_random_string(30))
for u in message.chmembers:
room.members.add(u)
# here can be somethis like this
# try
reply_channel = Channels.objects.get(online=True, user=u)
Group('%s' % r.name).add(reply_channel)
Group('%s' % room.name).send({
"text": "%s : %s" % (message.user.username, message['text']),
})
#channel_session_user
def ws_disconnect(message):
prefix, label = message['path'].strip('/').split('/')
Group(label).discard(message.reply_channel)
Simply make "automatic unique rooms" for user pairs. The rest stays the same. For example like this
def get_group_name(user1, user2):
return 'chat-{}-{}'.format(*sorted([user1.id, user2.id]))
Give it two user objects, and it returns a unique room for that pair of users, ordered the User.id, something like "chat-1-2" for the users with User.id "1" and "2".
That way, a user can connect with more than one logged-in device and still get the messages sent between the two users.
You can get the authenticated user's object from message.user.
For the receiving User object, I'd just sent the username along with the message. Then you can unpack it from the message['text'] the same way you unpack the actual message.
payload = json.loads(message.content['text'])
msg = payload['msg']
sender = message.user
receiver = get_object_or_404(User, username=payload['receiver'])
# ... here you could check if they have required permission ...
group_name = get_group_name(sender, receiver)
response = {'msg': msg}
Group(group_name).send({'text': json.dumps(response)})
# ... here you could persist the message in a database ...
So with that, you can drop all the "room" things from your example, including the room table etc. Because group names are always created on-the-fly when a message is send between two users.
Another important thing: One user will connect later than the other user, and may miss initial messages. So when you connect, you probably want to check some "chat_messages" database table, fetch the last 10 or 20 messages between the user pair, and send those back. So users can catch up on their past conversation.
Can anybody help me to fix this code, I really need it, but have no idea what to do next. I need to create a groupchat and send messega to invited persons, now it is example2#gmail.com, but it does not...
Is there mistake?
#!/usr/bin/python
import sys,os,xmpp,time
jid = 'example1#gmail.com'
psw = 'psw'
jid=xmpp.protocol.JID(jid)
cl=xmpp.Client(jid.getDomain(),debug=[])
cl.connect()
cl.auth(jid.getNode(),psw)
node = jid.getNode()
domain = 'talk.google.com'
room = node + '#' + domain
nroom = room + '/' + 'Maria'
mes = xmpp.Presence(to=nroom)
cl.sendInitPresence()
cl.send(mes)
NS_MUCUSER = 'http://jabber.org/protocol/muc#user'
invite = xmpp.simplexml.Node('invite')
invite.setAttr('to', 'example2#gmail.com')
invite.setTagData('reason', 'I really need it!')
mess = xmpp.Message(to=room)
mess.setTag('x', namespace=NS_MUCUSER).addChild(node=invite)
cl.send(mess)
msg = xmpp.protocol.Message(body="Hello there!")
msg.setTo(room)
msg.setType('groupchat')
cl.send(msg)
time.sleep(1) # some older servers will not send the message if you disconnect immediately after sending
cl.disconnect()
print "Done"
According to the specs - http://xmpp.org/extensions/xep-0045.html#createroom - sending a request to join a room that doesn't exist should create that room (or MUC)
The workflow for creating and configuring such rooms is as follows:
The user sends presence to <room#service/nick> and signal his or her support
for the Multi-User Chat protocol by including extended presence information
in an empty <x/> child element qualified by the 'http://jabber.org/protocol/muc'
namespace (note the lack of an '#owner' or '#user' fragment).
If this user is allowed to create a room and the room does not yet exist, the
service MUST create the room according to some default configuration, assign the
requesting user as the initial room owner, and add the owner to the room but not
allow anyone else to enter the room (effectively "locking" the room). The initial
presence stanza received by the owner from the room MUST include extended
presence information indicating the user's status as an owner and acknowledging
that the room has been created (via status code 201) and is awaiting
configuration.
So something like this is supposed to work according to the documentation.
jid=xmpp.protocol.JID('example#gmail.com')
cl=xmpp.Client(jid.getDomain(),debug=[])
jid = xmpp.protocol.JID('example#gmail.com')
client = xmpp.Client(jid.getDomain(), debug=[])
client.connect()
client.auth(jid.getNode(), 'my secret password')
client.send(xmpp.Presence(to='room#talk.google.com/ANick')
I find my mistake. Problem is that I didn't wait enough to get answer from the server and I invited people before server was able to create a chat room. Now I wait until I get answer from server and then send invite message.