Slixfeed/slixfeed/xmpp/component.py
2024-02-04 17:08:12 +00:00

280 lines
9.3 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FIXME
1) Function check_readiness or event "changed_status" is causing for
triple status messages and also false ones that indicate of lack
of feeds.
TODO
1) Use loop (with gather) instead of TaskGroup.
2) Assure message delivery before calling a new task.
See https://slixmpp.readthedocs.io/en/latest/event_index.html#term-marker_acknowledged
3) XHTTML-IM
case _ if message_lowercase.startswith("html"):
message['html']="
Parse me!
"
self.send_message(
mto=jid,
mfrom=self.boundjid.bare,
mhtml=message
)
NOTE
1) Self presence
Apparently, it is possible to view self presence.
This means that there is no need to store presences in order to switch or restore presence.
check_readiness
📂 Send a URL from a blog or a news website.
JID: self.boundjid.bare
MUC: self.alias
2) Extracting attribute using xmltodict.
import xmltodict
message = xmltodict.parse(str(message))
jid = message["message"]["x"]["@jid"]
"""
import asyncio
import logging
# import os
from random import randrange
import slixmpp
import slixfeed.task as task
from time import sleep
from slixmpp.plugins.xep_0363.http_upload import FileTooBig, HTTPError, UploadServiceNotFound
# from slixmpp.plugins.xep_0402 import BookmarkStorage, Conference
from slixmpp.plugins.xep_0048.stanza import Bookmarks
# import xmltodict
# import xml.etree.ElementTree as ET
# from lxml import etree
# import slixfeed.xmpp.bookmark as bookmark
import slixfeed.xmpp.connect as connect
# NOTE MUC is possible for component
# import slixfeed.xmpp.muc as muc
import slixfeed.xmpp.process as process
import slixfeed.xmpp.profile as profile
# import slixfeed.xmpp.roster as roster
# import slixfeed.xmpp.service as service
import slixfeed.xmpp.state as state
import slixfeed.xmpp.status as status
import slixfeed.xmpp.utility as utility
main_task = []
jid_tasker = {}
task_manager = {}
loop = asyncio.get_event_loop()
# asyncio.set_event_loop(loop)
# time_now = datetime.now()
# time_now = time_now.strftime("%H:%M:%S")
# def print_time():
# # return datetime.now().strftime("%H:%M:%S")
# now = datetime.now()
# current_time = now.strftime("%H:%M:%S")
# return current_time
class SlixfeedComponent(slixmpp.ComponentXMPP):
def __init__(self, jid, secret, hostname, port, alias=None):
slixmpp.ComponentXMPP.__init__(self, jid, secret, hostname, port)
# The session_start event will be triggered when
# the bot establishes its connection with the server
# and the XML streams are ready for use. We want to
# listen for this event so that we we can initialize
# our roster.
self.add_event_handler("session_start", self.on_session_start)
self.add_event_handler("session_resumed", self.on_session_resumed)
self.add_event_handler("got_offline", print("got_offline"))
# self.add_event_handler("got_online", self.check_readiness)
self.add_event_handler("changed_status", self.on_changed_status)
self.add_event_handler("presence_available", self.on_presence_available)
self.add_event_handler("presence_unavailable", self.on_presence_unavailable)
self.add_event_handler("chatstate_active", self.on_chatstate_active)
self.add_event_handler("chatstate_gone", self.on_chatstate_gone)
self.add_event_handler("chatstate_composing", self.check_chatstate_composing)
self.add_event_handler("chatstate_paused", self.check_chatstate_paused)
# The message event is triggered whenever a message
# stanza is received. Be aware that that includes
# MUC messages and error messages.
self.add_event_handler("message", self.on_message)
self.add_event_handler("groupchat_invite", self.on_groupchat_invite) # XEP_0045
self.add_event_handler("groupchat_direct_invite", self.on_groupchat_direct_invite) # XEP_0249
# self.add_event_handler("groupchat_message", self.message)
# self.add_event_handler("disconnected", self.reconnect)
# self.add_event_handler("disconnected", self.inspect_connection)
self.add_event_handler("reactions", self.on_reactions)
self.add_event_handler("presence_error", self.on_presence_error)
self.add_event_handler("presence_subscribe", self.on_presence_subscribe)
self.add_event_handler("presence_subscribed", self.on_presence_subscribed)
self.add_event_handler("presence_unsubscribed", self.on_presence_unsubscribed)
# Initialize event loop
# self.loop = asyncio.get_event_loop()
# handlers for connection events
self.connection_attempts = 0
self.max_connection_attempts = 10
self.add_event_handler("connection_failed", self.on_connection_failed)
self.add_event_handler("session_end", self.on_session_end)
# async def on_groupchat_invite(self, message):
# logging.warning("on_groupchat_invite")
# inviter = message["from"].bare
# muc_jid = message['groupchat_invite']['jid']
# await muc.join(self, inviter, muc_jid)
# await bookmark.add(self, muc_jid)
# NOTE Tested with Gajim and Psi
# async def on_groupchat_direct_invite(self, message):
# inviter = message["from"].bare
# muc_jid = message['groupchat_invite']['jid']
# await muc.join(self, inviter, muc_jid)
# await bookmark.add(self, muc_jid)
async def on_session_end(self, event):
message = "Session has ended."
await connect.recover_connection(self, message)
async def on_connection_failed(self, event):
message = "Connection has failed. Reason: {}".format(event)
await connect.recover_connection(self, message)
async def on_session_start(self, event):
self.send_presence()
await process.event_component(self)
# await muc.autojoin(self)
profile.set_identity(self, "service")
await profile.update(self)
connect.ping_task(self)
# await Service.capabilities(self)
# Service.commands(self)
# Service.reactions(self)
await self.service_capabilities()
self.service_commands()
self.service_reactions()
async def on_session_resumed(self, event):
await process.event_component(self)
# await muc.autojoin(self)
profile.set_identity(self, "service")
# await Service.capabilities(self)
# Service.commands(self)
# Service.reactions(self)
await self.service_capabilities()
self.service_commands()
self.service_reactions()
# TODO Request for subscription
async def on_message(self, message):
# jid = message["from"].bare
# if "chat" == await utility.get_chat_type(self, jid):
# await roster.add(self, jid)
# await state.request(self, jid)
await process.message(self, message)
# chat_type = message["type"]
# message_body = message["body"]
# message_reply = message.reply
async def on_changed_status(self, presence):
await task.check_readiness(self, presence)
async def on_presence_subscribe(self, presence):
jid = presence["from"].bare
# await state.request(self, jid)
self.send_presence_subscription(
pto=jid,
pfrom=self.boundjid.bare,
ptype="subscribe",
pnick=self.alias
)
async def on_presence_subscribed(self, presence):
jid = presence["from"].bare
process.greet(self, jid)
async def on_presence_available(self, presence):
# TODO Add function to check whether task is already running or not
await task.start_tasks(self, presence)
async def on_presence_unsubscribed(self, presence):
await state.unsubscribed(self, presence)
async def on_presence_unavailable(self, presence):
jid = presence["from"].bare
await task.stop_tasks(self, jid)
async def on_presence_error(self, presence):
print("on_presence_error")
print(presence)
async def on_reactions(self, message):
print(message['from'])
print(message['reactions']['values'])
async def on_chatstate_active(self, message):
if message['type'] in ('chat', 'normal'):
jid = message['from'].bare
await task.clean_tasks_xmpp(jid, ['status'])
await task.start_tasks_xmpp(self, jid, ['status'])
async def on_chatstate_gone(self, message):
if message['type'] in ('chat', 'normal'):
jid = message['from'].bare
await task.clean_tasks_xmpp(jid, ['status'])
await task.start_tasks_xmpp(self, jid, ['status'])
async def check_chatstate_composing(self, message):
if message['type'] in ('chat', 'normal'):
jid = message['from'].bare
await task.clean_tasks_xmpp(jid, ['status'])
status_text='Press "help" for manual, or "info" for information.'
status.send(self, jid, status_text)
async def check_chatstate_paused(self, message):
if message['type'] in ('chat', 'normal'):
jid = message['from'].bare
await task.clean_tasks_xmpp(jid, ['status'])
await task.start_tasks_xmpp(self, jid, ['status'])