Python : Set OMEMO as an optional dependency;
SVG : Add a selection of variations of the Slixfeed logo.
This commit is contained in:
parent
3913f740ef
commit
178f49cb86
13 changed files with 408 additions and 135 deletions
11
README.md
11
README.md
|
@ -57,9 +57,20 @@ It is possible to install Slixfeed using pip and pipx.
|
|||
```
|
||||
$ python3 -m venv .venv
|
||||
$ source .venv/bin/activate
|
||||
```
|
||||
|
||||
##### Install
|
||||
|
||||
```
|
||||
$ pip install git+https://git.xmpp-it.net/sch/Slixfeed
|
||||
```
|
||||
|
||||
##### Install (OMEMO)
|
||||
|
||||
```
|
||||
$ pip install git+https://git.xmpp-it.net/sch/Slixfeed[omemo]
|
||||
```
|
||||
|
||||
#### pipx
|
||||
|
||||
##### Install
|
||||
|
|
|
@ -37,33 +37,36 @@ keywords = [
|
|||
"xml",
|
||||
"xmpp",
|
||||
]
|
||||
|
||||
# urls = {Homepage = "https://gitgud.io/sjehuda/slixfeed"}
|
||||
|
||||
dependencies = [
|
||||
"aiofiles",
|
||||
"aiohttp",
|
||||
# "daemonize",
|
||||
"feedparser",
|
||||
"lxml",
|
||||
"omemo", # OMEMO
|
||||
# "pysocks",
|
||||
"protobuf==3.20.3", # OMEMO
|
||||
"python-dateutil",
|
||||
"requests",
|
||||
"slixmpp",
|
||||
"slixmpp-omemo", # OMEMO
|
||||
"tomli", # Python 3.10
|
||||
"tomli_w",
|
||||
"X3DH", # OMEMO
|
||||
"XEdDSA", # OMEMO
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "http://slixfeed.i2p/"
|
||||
Repository = "https://gitgud.io/sjehuda/slixfeed"
|
||||
Homepage = "https://slixfeed.woodpeckersnest.space"
|
||||
Repository = "https://git.xmpp-it.net/sch/Slixfeed"
|
||||
Issues = "https://gitgud.io/sjehuda/slixfeed/issues"
|
||||
|
||||
|
||||
[project.optional-dependencies]
|
||||
omemo = [
|
||||
"DoubleRatchet>=0.7.0,<0.8",
|
||||
"OMEMO>=0.13.0,<0.15",
|
||||
"protobuf==3.20.3",
|
||||
"slixmpp-omemo",
|
||||
"X3DH>=0.5.9,<0.6",
|
||||
"XEdDSA<0.5,>=0.4.7",
|
||||
]
|
||||
proxy = ["pysocks"]
|
||||
|
||||
# [project.readme]
|
||||
|
|
|
@ -28,9 +28,9 @@ Good luck!
|
|||
|
||||
filetypes = "Atom, JSON, RDF, RSS, XML."
|
||||
platforms = "XMPP"
|
||||
# platforms = "ActivityPub, Briar, DeltaChat, Email, IRC, LXMF, MQTT, Nostr, Session, Tox."
|
||||
# platforms = "ActivityPub, BitMessage, Briar, DeltaChat, Email, IRC, LXMF, MQTT, Nostr, Session, Tox."
|
||||
comment = "For ideal experience, we recommend using XMPP." # Nostr, Session or DeltaChat
|
||||
url = "https://gitgud.io/sjehuda/slixfeed"
|
||||
url = "https://git.xmpp-it.net/sch/Slixfeed"
|
||||
|
||||
[[about]]
|
||||
name = "slixmpp"
|
||||
|
@ -260,7 +260,7 @@ Slixfeed is distributed in the hope that it will be useful, but WITHOUT ANY \
|
|||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR \
|
||||
A PARTICULAR PURPOSE. See the MIT License for more details.
|
||||
"""]
|
||||
link = "https://gitgud.io/sjehuda/slixfeed"
|
||||
link = "https://git.xmpp-it.net/sch/Slixfeed"
|
||||
|
||||
[[license]]
|
||||
title = "License"
|
||||
|
|
|
@ -1 +1,48 @@
|
|||
<svg height="600" width="600" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0zm0 0" style="fill:#ffa000" transform="translate(44 44)"/><path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279zm0 0" style="fill:#ffa000" transform="translate(44 44)"/><path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47Zm0 0" style="fill:#ffa000" transform="translate(44 44)"/></svg>
|
||||
<svg height="600" width="600" xmlns="http://www.w3.org/2000/svg" xml:space="preserve">
|
||||
<defs>
|
||||
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feGaussianBlur in="SourceAlpha" stdDeviation="5" />
|
||||
<feOffset dx="5" dy="5" result="offsetblur" />
|
||||
<feFlood flood-color="rgba(0,0,0,0.5)" />
|
||||
<feComposite in2="offsetblur" operator="in" />
|
||||
<feMerge>
|
||||
<feMergeNode />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
|
||||
<!-- Glass Gradient -->
|
||||
<linearGradient id="glassGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:rgba(255, 255, 255, 0.3); stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:rgba(255, 255, 255, 0.1); stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Black shapes with orange margins -->
|
||||
<path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0z"
|
||||
style="fill:#ffa000; stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279z"
|
||||
style="fill:#ffa000; stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47z"
|
||||
style="fill:#ffa000; stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<!-- Glass Shadow Effect Layer -->
|
||||
<g filter="url(#shadow)">
|
||||
<path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 2 KiB |
48
slixfeed/assets/image_black.svg
Normal file
48
slixfeed/assets/image_black.svg
Normal file
|
@ -0,0 +1,48 @@
|
|||
<svg height="600" width="600" xmlns="http://www.w3.org/2000/svg" xml:space="preserve">
|
||||
<defs>
|
||||
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feGaussianBlur in="SourceAlpha" stdDeviation="5" />
|
||||
<feOffset dx="5" dy="5" result="offsetblur" />
|
||||
<feFlood flood-color="rgba(0,0,0,0.5)" />
|
||||
<feComposite in2="offsetblur" operator="in" />
|
||||
<feMerge>
|
||||
<feMergeNode />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
|
||||
<!-- Glass Gradient -->
|
||||
<linearGradient id="glassGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:rgba(255, 255, 255, 0.3); stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:rgba(255, 255, 255, 0.1); stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Black shapes with orange margins -->
|
||||
<path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0z"
|
||||
style="fill:#000000; stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279z"
|
||||
style="fill:#000000; stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47z"
|
||||
style="fill:#000000; stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<!-- Glass Shadow Effect Layer -->
|
||||
<g filter="url(#shadow)">
|
||||
<path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
51
slixfeed/assets/image_semi_transparent.svg
Normal file
51
slixfeed/assets/image_semi_transparent.svg
Normal file
|
@ -0,0 +1,51 @@
|
|||
<svg height="600" width="600" xmlns="http://www.w3.org/2000/svg" xml:space="preserve">
|
||||
<defs>
|
||||
<!-- Gradient for Glass Effect -->
|
||||
<linearGradient id="glassGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:rgba(255, 255, 255, 0.5); stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:rgba(0, 0, 0, 0.2); stop-opacity:1" />
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient id="glassHighlight" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style="stop-color:rgba(255, 255, 255, 0.8); stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:rgba(255, 255, 255, 0); stop-opacity:1" />
|
||||
</linearGradient>
|
||||
|
||||
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feGaussianBlur in="SourceAlpha" stdDeviation="5" />
|
||||
<feOffset dx="5" dy="5" result="offsetblur" />
|
||||
<feFlood flood-color="rgba(0, 0, 0, 0.3)" />
|
||||
<feComposite in2="offsetblur" operator="in" />
|
||||
<feMerge>
|
||||
<feMergeNode />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<!-- Shapes with Glass Effect -->
|
||||
<path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0z"
|
||||
style="fill:url(#glassGradient); stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279z"
|
||||
style="fill:url(#glassGradient); stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47z"
|
||||
style="fill:url(#glassGradient); stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<!-- Highlights for Shiny Effect -->
|
||||
<path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0z"
|
||||
style="fill:url(#glassHighlight); opacity:0.6;"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279z"
|
||||
style="fill:url(#glassHighlight); opacity:0.6;"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47z"
|
||||
style="fill:url(#glassHighlight); opacity:0.6;"
|
||||
transform="translate(44 44)" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
48
slixfeed/assets/image_transparent.svg
Normal file
48
slixfeed/assets/image_transparent.svg
Normal file
|
@ -0,0 +1,48 @@
|
|||
<svg height="600" width="600" xmlns="http://www.w3.org/2000/svg" xml:space="preserve">
|
||||
<defs>
|
||||
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feGaussianBlur in="SourceAlpha" stdDeviation="5" />
|
||||
<feOffset dx="5" dy="5" result="offsetblur" />
|
||||
<feFlood flood-color="rgba(0,0,0,0.5)" />
|
||||
<feComposite in2="offsetblur" operator="in" />
|
||||
<feMerge>
|
||||
<feMergeNode />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
|
||||
<!-- Glass Gradient -->
|
||||
<linearGradient id="glassGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:rgba(255, 255, 255, 0.3); stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:rgba(255, 255, 255, 0.1); stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Black shapes with orange margins -->
|
||||
<path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0z"
|
||||
style="fill:url(#glassGradient); stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279z"
|
||||
style="fill:url(#glassGradient); stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47z"
|
||||
style="fill:url(#glassGradient); stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<!-- Glass Shadow Effect Layer -->
|
||||
<g filter="url(#shadow)">
|
||||
<path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
48
slixfeed/assets/image_white.svg
Normal file
48
slixfeed/assets/image_white.svg
Normal file
|
@ -0,0 +1,48 @@
|
|||
<svg height="600" width="600" xmlns="http://www.w3.org/2000/svg" xml:space="preserve">
|
||||
<defs>
|
||||
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
||||
<feGaussianBlur in="SourceAlpha" stdDeviation="5" />
|
||||
<feOffset dx="5" dy="5" result="offsetblur" />
|
||||
<feFlood flood-color="rgba(0,0,0,0.5)" />
|
||||
<feComposite in2="offsetblur" operator="in" />
|
||||
<feMerge>
|
||||
<feMergeNode />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
|
||||
<!-- Glass Gradient -->
|
||||
<linearGradient id="glassGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:rgba(255, 255, 255, 0.3); stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:rgba(255, 255, 255, 0.1); stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Black shapes with orange margins -->
|
||||
<path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0z"
|
||||
style="fill:#ffffff; stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279z"
|
||||
style="fill:#ffffff; stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47z"
|
||||
style="fill:#ffffff; stroke:#e15a00; stroke-width:10; filter:url(#shadow);"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<!-- Glass Shadow Effect Layer -->
|
||||
<g filter="url(#shadow)">
|
||||
<path d="M167 406a60 60 0 1 1-120 0 60 60 0 0 1 120 0z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 186v80c110 0 199 89 199 199h80c0-154-125-279-279-279z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
|
||||
<path d="M47 47v79c187 0 338 152 338 339h80C465 234 277 47 47 47z"
|
||||
style="fill:url(#glassGradient); stroke:none;"
|
||||
transform="translate(44 44)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
|
@ -3032,7 +3032,7 @@ def check_entry_exist(db_file, feed_id, identifier=None, title=None, link=None,
|
|||
"""
|
||||
SELECT id
|
||||
FROM entries_properties
|
||||
WHERE identifier = :identifier and feed_id = :feed_id
|
||||
WHERE identifier = :identifier AND feed_id = :feed_id
|
||||
"""
|
||||
)
|
||||
par = {
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
__version__ = '0.1.94'
|
||||
__version_info__ = (0, 1, 94)
|
||||
__version__ = '0.1.95'
|
||||
__version_info__ = (0, 1, 95)
|
||||
|
|
|
@ -36,7 +36,6 @@ import slixfeed.sqlite as sqlite
|
|||
from slixfeed.syndication import FeedTask
|
||||
from slixfeed.utilities import Documentation, Html, MD, Task, Url
|
||||
from slixfeed.xmpp.commands import XmppCommands
|
||||
from slixfeed.xmpp.encryption import XmppOmemo
|
||||
from slixfeed.xmpp.message import XmppMessage
|
||||
from slixfeed.xmpp.presence import XmppPresence
|
||||
from slixfeed.xmpp.status import XmppStatusTask
|
||||
|
@ -48,6 +47,10 @@ import sys
|
|||
import time
|
||||
from typing import Optional
|
||||
|
||||
try:
|
||||
from slixfeed.xmpp.encryption import XmppOmemo
|
||||
except Exception as e:
|
||||
print('Encryption of type OMEMO is not enabled. Reason: ' + str(e))
|
||||
|
||||
logger = Logger(__name__)
|
||||
|
||||
|
@ -150,7 +153,7 @@ class XmppChat:
|
|||
|
||||
# await compose.message(self, jid_bare, message)
|
||||
|
||||
if self['xep_0384'].is_encrypted(message):
|
||||
if self.omemo_present and self['xep_0384'].is_encrypted(message):
|
||||
allow_untrusted=True # Temporary fix. This should be handled by "retry""
|
||||
command, omemo_decrypted, retry = await XmppOmemo.decrypt(
|
||||
self, message, allow_untrusted)
|
||||
|
@ -229,8 +232,8 @@ class XmppChat:
|
|||
case _ if command_lowercase in ['greetings', 'hallo', 'hello',
|
||||
'hey', 'hi', 'hola', 'holla',
|
||||
'hollo']:
|
||||
response = ('Greeting! My name is {}.\n'
|
||||
'I am an RSS News Bot.\n'
|
||||
response = ('Greeting. My name is {}.\n'
|
||||
'I am an Atom/RSS News Bot.\n'
|
||||
'Send "help" for further instructions.\n'
|
||||
.format(self.alias))
|
||||
case _ if command_lowercase.startswith('add'):
|
||||
|
@ -358,7 +361,7 @@ class XmppChat:
|
|||
# XmppMessage.send_oob_reply_message(message, url, response)
|
||||
if url:
|
||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||
if encrypted:
|
||||
if self.omemo_present and encrypted:
|
||||
url_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||
self, message_from, url)
|
||||
XmppMessage.send_omemo_oob(self, message_from, url_encrypted, chat_type)
|
||||
|
@ -591,7 +594,7 @@ class XmppChat:
|
|||
response = XmppCommands.search_items(db_file, query)
|
||||
case 'start':
|
||||
status_type = 'available'
|
||||
status_message = '📫️ Welcome back!'
|
||||
status_message = '📫️ Welcome back.'
|
||||
XmppPresence.send(self, jid_bare, status_message,
|
||||
status_type=status_type)
|
||||
await asyncio.sleep(5)
|
||||
|
@ -627,7 +630,7 @@ class XmppChat:
|
|||
if response:
|
||||
encrypt_omemo = Config.get_setting_value(self, jid_bare, 'omemo')
|
||||
encrypted = True if encrypt_omemo else False
|
||||
if encrypted and self['xep_0384'].is_encrypted(message):
|
||||
if self.omemo_present and encrypted and self['xep_0384'].is_encrypted(message):
|
||||
response_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||
self, message_from, response)
|
||||
if omemo_decrypted and omemo_encrypted:
|
||||
|
@ -732,17 +735,17 @@ class XmppChatAction:
|
|||
media_url = None
|
||||
|
||||
if media_url and news_digest:
|
||||
if encrypt_omemo:
|
||||
if self.omemo_present and encrypt_omemo:
|
||||
news_digest_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||
self, jid, news_digest)
|
||||
if encrypt_omemo and omemo_encrypted:
|
||||
if self.omemo_present and encrypt_omemo and omemo_encrypted:
|
||||
XmppMessage.send_omemo(self, jid, chat_type, news_digest_encrypted)
|
||||
else:
|
||||
# Send textual message
|
||||
XmppMessage.send(self, jid_bare, news_digest, chat_type)
|
||||
news_digest = ''
|
||||
# Send media
|
||||
if encrypt_omemo:
|
||||
if self.omemo_present and encrypt_omemo:
|
||||
cache_dir = config.get_default_cache_directory()
|
||||
# if not media_url.startswith('data:'):
|
||||
filename = media_url.split('/').pop().split('?')[0]
|
||||
|
@ -796,9 +799,10 @@ class XmppChatAction:
|
|||
media_url = None
|
||||
|
||||
if news_digest:
|
||||
if encrypt_omemo: news_digest_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||
if self.omemo_present and encrypt_omemo:
|
||||
news_digest_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||
self, jid, news_digest)
|
||||
if encrypt_omemo and omemo_encrypted:
|
||||
if self.omemo_present and encrypt_omemo and omemo_encrypted:
|
||||
XmppMessage.send_omemo(self, jid, chat_type, news_digest_encrypted)
|
||||
else:
|
||||
XmppMessage.send(self, jid_bare, news_digest, chat_type)
|
||||
|
|
|
@ -54,7 +54,6 @@ from slixfeed.version import __version__
|
|||
from slixfeed.xmpp.bookmark import XmppBookmark
|
||||
from slixfeed.xmpp.chat import XmppChat, XmppChatTask
|
||||
from slixfeed.xmpp.connect import XmppConnect, XmppConnectTask
|
||||
from slixfeed.xmpp.encryption import XmppOmemo
|
||||
from slixfeed.xmpp.groupchat import XmppGroupchat
|
||||
from slixfeed.xmpp.ipc import XmppIpcServer
|
||||
from slixfeed.xmpp.iq import XmppIQ
|
||||
|
@ -69,8 +68,6 @@ from slixfeed.xmpp.status import XmppStatusTask
|
|||
from slixfeed.xmpp.upload import XmppUpload
|
||||
from slixfeed.xmpp.utilities import XmppUtilities
|
||||
from slixmpp import JID
|
||||
import slixmpp_omemo
|
||||
from slixmpp_omemo import PluginCouldNotLoad
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
@ -154,6 +151,17 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
self.register_plugin('xep_0363') # HTTP File Upload
|
||||
self.register_plugin('xep_0402') # PEP Native Bookmarks
|
||||
self.register_plugin('xep_0444') # Message Reactions
|
||||
|
||||
try:
|
||||
from slixfeed.xmpp.encryption import XmppOmemo
|
||||
import slixmpp_omemo
|
||||
from slixmpp_omemo import PluginCouldNotLoad
|
||||
self.omemo_present = True
|
||||
except Exception as e:
|
||||
print('Encryption of type OMEMO is not enabled. Reason: ' + str(e))
|
||||
self.omemo_present = False
|
||||
|
||||
if self.omemo_present:
|
||||
try:
|
||||
self.register_plugin(
|
||||
'xep_0384',
|
||||
|
@ -868,7 +876,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
.format(function_name, jid_full))
|
||||
jid_bare = session['from'].bare
|
||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
||||
if XmppUtilities.is_access(self, jid, chat_type):
|
||||
form = self['xep_0004'].make_form('form', 'PubSub')
|
||||
form['instructions'] = 'Publish news items to PubSub nodes.'
|
||||
options = form.add_field(desc='From which medium source do you '
|
||||
|
@ -889,16 +897,16 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
session['prev'] = None
|
||||
session['payload'] = form
|
||||
else:
|
||||
if not XmppUtilities.is_operator(self, jid_bare):
|
||||
if chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
elif not XmppUtilities.is_operator(self, jid_bare):
|
||||
text_warn = 'This resource is restricted to operators.'
|
||||
elif chat_type == 'groupchat':
|
||||
text_warn = ('This resource is restricted to moderators of {}.'
|
||||
.format(jid_bare))
|
||||
elif chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
else:
|
||||
text_warn = 'This resource is forbidden.'
|
||||
text_warn = 'This resource is restricted.'
|
||||
session['notes'] = [['warn', text_warn]]
|
||||
return session
|
||||
|
||||
|
@ -909,7 +917,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
.format(function_name, jid_full))
|
||||
jid_bare = session['from'].bare
|
||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
||||
if XmppUtilities.is_access(self, jid, chat_type):
|
||||
values = payload['values']
|
||||
form = self['xep_0004'].make_form('form', 'Publish')
|
||||
form['instructions'] = ('Choose a PubSub Jabber ID and verify '
|
||||
|
@ -997,16 +1005,16 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
session['has_next'] = True
|
||||
session['prev'] = self._handle_publish
|
||||
else:
|
||||
if not XmppUtilities.is_operator(self, jid_bare):
|
||||
if chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
elif not XmppUtilities.is_operator(self, jid_bare):
|
||||
text_warn = 'This resource is restricted to operators.'
|
||||
elif chat_type == 'groupchat':
|
||||
text_warn = ('This resource is restricted to moderators of {}.'
|
||||
.format(jid_bare))
|
||||
elif chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
else:
|
||||
text_warn = 'This resource is forbidden.'
|
||||
text_warn = 'This resource is restricted.'
|
||||
session['notes'] = [['warn', text_warn]]
|
||||
return session
|
||||
|
||||
|
@ -1413,13 +1421,14 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
return session
|
||||
|
||||
async def _handle_filters(self, iq, session):
|
||||
jid = session['from']
|
||||
jid_full = session['from'].full
|
||||
function_name = sys._getframe().f_code.co_name
|
||||
logger.debug('{}: jid_full: {}'
|
||||
.format(function_name, jid_full))
|
||||
jid_bare = session['from'].bare
|
||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
||||
if XmppUtilities.is_access(self, jid, chat_type):
|
||||
jid = session['from'].bare
|
||||
db_file = config.get_pathname_to_database(jid_bare)
|
||||
form = self['xep_0004'].make_form('form', 'Filters')
|
||||
|
@ -1458,16 +1467,16 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
session['next'] = self._handle_filters_complete
|
||||
session['payload'] = form
|
||||
else:
|
||||
if not XmppUtilities.is_operator(self, jid_bare):
|
||||
if chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
elif not XmppUtilities.is_operator(self, jid_bare):
|
||||
text_warn = 'This resource is restricted to operators.'
|
||||
elif chat_type == 'groupchat':
|
||||
text_warn = ('This resource is restricted to moderators of {}.'
|
||||
.format(jid_bare))
|
||||
elif chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
else:
|
||||
text_warn = 'This resource is forbidden.'
|
||||
text_warn = 'This resource is restricted.'
|
||||
session['notes'] = [['warn', text_warn]]
|
||||
return session
|
||||
|
||||
|
@ -1522,13 +1531,14 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
|
||||
|
||||
async def _handle_subscription_add(self, iq, session):
|
||||
jid = session['from']
|
||||
jid_full = session['from'].full
|
||||
function_name = sys._getframe().f_code.co_name
|
||||
logger.debug('{}: jid_full: {}'
|
||||
.format(function_name, jid_full))
|
||||
jid_bare = session['from'].bare
|
||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
||||
if XmppUtilities.is_access(self, jid, chat_type):
|
||||
form = self['xep_0004'].make_form('form', 'Subscribe')
|
||||
# form['instructions'] = 'Add a new custom subscription.'
|
||||
form.add_field(desc='Enter a URL.',
|
||||
|
@ -1570,16 +1580,16 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
session['prev'] = None
|
||||
session['payload'] = form
|
||||
else:
|
||||
if not XmppUtilities.is_operator(self, jid_bare):
|
||||
if chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
elif not XmppUtilities.is_operator(self, jid_bare):
|
||||
text_warn = 'This resource is restricted to operators.'
|
||||
elif chat_type == 'groupchat':
|
||||
text_warn = ('This resource is restricted to moderators of {}.'
|
||||
.format(jid_bare))
|
||||
elif chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
else:
|
||||
text_warn = 'This resource is forbidden.'
|
||||
text_warn = 'This resource is restricted.'
|
||||
session['notes'] = [['warn', text_warn]]
|
||||
return session
|
||||
|
||||
|
@ -2036,13 +2046,14 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
|
||||
|
||||
async def _handle_discover(self, iq, session):
|
||||
jid = session['from']
|
||||
jid_full = session['from'].full
|
||||
function_name = sys._getframe().f_code.co_name
|
||||
logger.debug('{}: jid_full: {}'
|
||||
.format(function_name, jid_full))
|
||||
jid_bare = session['from'].bare
|
||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
||||
if XmppUtilities.is_access(self, jid, chat_type):
|
||||
form = self['xep_0004'].make_form('form', 'Discover & Search')
|
||||
form['instructions'] = 'Discover news subscriptions of all kinds'
|
||||
options = form.add_field(desc='Select type of search.',
|
||||
|
@ -2059,16 +2070,16 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
session['payload'] = form
|
||||
session['prev'] = None
|
||||
else:
|
||||
if not XmppUtilities.is_operator(self, jid_bare):
|
||||
if chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
elif not XmppUtilities.is_operator(self, jid_bare):
|
||||
text_warn = 'This resource is restricted to operators.'
|
||||
elif chat_type == 'groupchat':
|
||||
text_warn = ('This resource is restricted to moderators of {}.'
|
||||
.format(jid_bare))
|
||||
elif chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
else:
|
||||
text_warn = 'This resource is forbidden.'
|
||||
text_warn = 'This resource is restricted.'
|
||||
session['notes'] = [['warn', text_warn]]
|
||||
return session
|
||||
|
||||
|
@ -2160,13 +2171,14 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
|
||||
|
||||
async def _handle_subscriptions(self, iq, session):
|
||||
jid = session['from']
|
||||
jid_full = session['from'].full
|
||||
function_name = sys._getframe().f_code.co_name
|
||||
logger.debug('{}: jid_full: {}'
|
||||
.format(function_name, jid_full))
|
||||
jid_bare = session['from'].bare
|
||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
||||
if XmppUtilities.is_access(self, jid, chat_type):
|
||||
form = self['xep_0004'].make_form('form', 'Subscriptions')
|
||||
form['instructions'] = ('Browse, view, toggle or remove '
|
||||
'tags and subscriptions.')
|
||||
|
@ -2210,16 +2222,16 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
session['next'] = self._handle_subscriptions_result
|
||||
session['has_next'] = True
|
||||
else:
|
||||
if not XmppUtilities.is_operator(self, jid_bare):
|
||||
if chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
elif not XmppUtilities.is_operator(self, jid_bare):
|
||||
text_warn = 'This resource is restricted to operators.'
|
||||
elif chat_type == 'groupchat':
|
||||
text_warn = ('This resource is restricted to moderators of {}.'
|
||||
.format(jid_bare))
|
||||
elif chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
else:
|
||||
text_warn = 'This resource is forbidden.'
|
||||
text_warn = 'This resource is restricted.'
|
||||
session['notes'] = [['warn', text_warn]]
|
||||
return session
|
||||
|
||||
|
@ -2520,13 +2532,13 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
|
||||
|
||||
async def _handle_advanced(self, iq, session):
|
||||
jid_full = session['from'].full
|
||||
jid = session['from']
|
||||
function_name = sys._getframe().f_code.co_name
|
||||
logger.debug('{}: jid_full: {}'
|
||||
.format(function_name, jid_full))
|
||||
logger.debug('{}: jid: {}'
|
||||
.format(function_name, jid))
|
||||
jid_bare = session['from'].bare
|
||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
||||
if XmppUtilities.is_access(self, jid, chat_type):
|
||||
form = self['xep_0004'].make_form('form', 'Advanced')
|
||||
form['instructions'] = 'Extended options'
|
||||
options = form.add_field(ftype='list-single',
|
||||
|
@ -2547,16 +2559,16 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
session['next'] = self._handle_advanced_result
|
||||
session['prev'] = self._handle_advanced
|
||||
else:
|
||||
if not XmppUtilities.is_operator(self, jid_bare):
|
||||
if chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
elif not XmppUtilities.is_operator(self, jid_bare):
|
||||
text_warn = 'This resource is restricted to operators.'
|
||||
elif chat_type == 'groupchat':
|
||||
text_warn = ('This resource is restricted to moderators of {}.'
|
||||
.format(jid_bare))
|
||||
elif chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
else:
|
||||
text_warn = 'This resource is forbidden.'
|
||||
text_warn = 'This resource is restricted.'
|
||||
session['notes'] = [['warn', text_warn]]
|
||||
return session
|
||||
|
||||
|
@ -2940,6 +2952,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
# TODO Attempt to look up for feeds of hostname of JID (i.e. scan
|
||||
# jabber.de for feeds for juliet@jabber.de)
|
||||
async def _handle_promoted(self, iq, session):
|
||||
jid = session['from']
|
||||
jid_full = session['from'].full
|
||||
function_name = sys._getframe().f_code.co_name
|
||||
logger.debug('{}: jid_full: {}'
|
||||
|
@ -2947,7 +2960,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
jid_bare = session['from'].bare
|
||||
jid_full = session['from'].full
|
||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
||||
if XmppUtilities.is_access(self, jid, chat_type):
|
||||
form = self['xep_0004'].make_form('form', 'Subscribe')
|
||||
# NOTE Refresh button would be of use
|
||||
form['instructions'] = 'Featured subscriptions'
|
||||
|
@ -2998,16 +3011,16 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
session['payload'] = form
|
||||
session['prev'] = self._handle_promoted
|
||||
else:
|
||||
if not XmppUtilities.is_operator(self, jid_bare):
|
||||
if chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
elif not XmppUtilities.is_operator(self, jid_bare):
|
||||
text_warn = 'This resource is restricted to operators.'
|
||||
elif chat_type == 'groupchat':
|
||||
text_warn = ('This resource is restricted to moderators of {}.'
|
||||
.format(jid_bare))
|
||||
elif chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
else:
|
||||
text_warn = 'This resource is forbidden.'
|
||||
text_warn = 'This resource is restricted.'
|
||||
session['notes'] = [['warn', text_warn]]
|
||||
return session
|
||||
|
||||
|
@ -3646,13 +3659,14 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
session. Additional, custom data may be saved
|
||||
here to persist across handler callbacks.
|
||||
"""
|
||||
jid = session['from']
|
||||
jid_full = session['from'].full
|
||||
function_name = sys._getframe().f_code.co_name
|
||||
logger.debug('{}: jid_full: {}'
|
||||
.format(function_name, jid_full))
|
||||
jid_bare = session['from'].bare
|
||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
||||
if XmppUtilities.is_access(self, jid, chat_type):
|
||||
db_file = config.get_pathname_to_database(jid_bare)
|
||||
if jid_bare not in self.settings:
|
||||
Config.add_settings_jid(self, jid_bare, db_file)
|
||||
|
@ -3750,16 +3764,16 @@ class XmppClient(slixmpp.ClientXMPP):
|
|||
session['next'] = self._handle_settings_complete
|
||||
session['payload'] = form
|
||||
else:
|
||||
if not XmppUtilities.is_operator(self, jid_bare):
|
||||
if chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
elif not XmppUtilities.is_operator(self, jid_bare):
|
||||
text_warn = 'This resource is restricted to operators.'
|
||||
elif chat_type == 'groupchat':
|
||||
text_warn = ('This resource is restricted to moderators of {}.'
|
||||
.format(jid_bare))
|
||||
elif chat_type == 'error':
|
||||
text_warn = ('Could not determine chat type of {}.'
|
||||
.format(jid_bare))
|
||||
else:
|
||||
text_warn = 'This resource is forbidden.'
|
||||
text_warn = 'This resource is restricted.'
|
||||
session['notes'] = [['warn', text_warn]]
|
||||
return session
|
||||
|
||||
|
|
|
@ -9,10 +9,8 @@ logger = Logger(__name__)
|
|||
# class XmppChat
|
||||
# class XmppUtility:
|
||||
|
||||
|
||||
class XmppUtilities:
|
||||
|
||||
|
||||
async def get_chat_type(self, jid):
|
||||
"""
|
||||
Check chat (i.e. JID) type.
|
||||
|
@ -60,21 +58,18 @@ class XmppUtilities:
|
|||
return result
|
||||
|
||||
|
||||
|
||||
def is_access(self, jid_bare, jid_full, chat_type):
|
||||
def is_access(self, jid, chat_type):
|
||||
"""Determine access privilege"""
|
||||
operator = XmppUtilities.is_operator(self, jid_bare)
|
||||
if operator:
|
||||
room = jid_bare = jid.bare
|
||||
alias = jid.resource
|
||||
if chat_type == 'groupchat':
|
||||
if XmppUtilities.is_moderator(self, jid_bare, jid_full):
|
||||
access = True
|
||||
access = True if XmppUtilities.is_moderator(self, room, alias) else False
|
||||
if access: print('Access granted to groupchat moderator ' + alias)
|
||||
else:
|
||||
print('Access granted to chat ' + jid_bare)
|
||||
access = True
|
||||
else:
|
||||
access = False
|
||||
return access
|
||||
|
||||
|
||||
def is_operator(self, jid_bare):
|
||||
"""Check if given JID is an operator"""
|
||||
result = False
|
||||
|
@ -85,24 +80,28 @@ class XmppUtilities:
|
|||
break
|
||||
return result
|
||||
|
||||
|
||||
def is_moderator(self, jid_bare, jid_full):
|
||||
"""Check if given JID is a moderator"""
|
||||
alias = jid_full[jid_full.index('/')+1:]
|
||||
role = self.plugin['xep_0045'].get_jid_property(jid_bare, alias, 'role')
|
||||
if role == 'moderator':
|
||||
result = True
|
||||
else:
|
||||
result = False
|
||||
def is_admin(self, room, alias):
|
||||
"""Check if given JID is an administrator"""
|
||||
affiliation = self.plugin['xep_0045'].get_jid_property(room, alias, 'affiliation')
|
||||
result = True if affiliation == 'admin' else False
|
||||
return result
|
||||
|
||||
def is_owner(self, room, alias):
|
||||
"""Check if given JID is an owner"""
|
||||
affiliation = self.plugin['xep_0045'].get_jid_property(room, alias, 'affiliation')
|
||||
result = True if affiliation == 'owner' else False
|
||||
return result
|
||||
|
||||
def is_moderator(self, room, alias):
|
||||
"""Check if given JID is a moderator"""
|
||||
role = self.plugin['xep_0045'].get_jid_property(room, alias, 'role')
|
||||
result = True if role == 'moderator' else False
|
||||
return result
|
||||
|
||||
# NOTE Would this properly work when Alias and Local differ?
|
||||
def is_member(self, jid_bare, jid_full):
|
||||
"""Check if given JID is a member"""
|
||||
alias = jid_full[jid_full.index('/')+1:]
|
||||
affiliation = self.plugin['xep_0045'].get_jid_property(jid_bare, alias, 'affiliation')
|
||||
if affiliation == 'member':
|
||||
result = True
|
||||
else:
|
||||
result = False
|
||||
result = True if affiliation == 'member' else False
|
||||
return result
|
Loading…
Reference in a new issue