Compare commits
5 Commits
34f1c0c47d
...
ae21c6f365
Author | SHA1 | Date |
---|---|---|
nicoco | ae21c6f365 | |
nicoco | e3c36becdc | |
nicoco | 4c88f75a88 | |
nicoco | c745aa4050 | |
nicoco | 065252fba4 |
|
@ -1,7 +1,6 @@
|
|||
image: debian/bookworm
|
||||
packages:
|
||||
- curl
|
||||
- golang
|
||||
- python-is-python3
|
||||
- python3-dev
|
||||
- python3-pybindgen
|
||||
|
@ -12,6 +11,10 @@ artifacts:
|
|||
- ./docs.tar.gz
|
||||
- ./package.tar
|
||||
tasks:
|
||||
- install-golang: |
|
||||
echo "deb http://deb.debian.org/debian bookworm-backports main"|sudo tee -a /etc/apt/sources.list
|
||||
sudo apt update
|
||||
sudo apt install -y golang -t bookworm-backports
|
||||
- install-poetry: |
|
||||
curl -sSL https://install.python-poetry.org | python3 -
|
||||
sudo ln -s ~/.local/bin/poetry /usr/local/bin
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
|
||||
_commit: ae31af1
|
||||
_commit: d5866b9
|
||||
_src_path: git+https://git.sr.ht/~nicoco/slidge-template
|
||||
author: deuill
|
||||
author_email: alex@deuill.org
|
||||
|
@ -17,10 +17,9 @@ srht_secret_docker: 173244e1-c233-43de-969f-65965c5487e1
|
|||
srht_secret_pypi: 3ecea679-dec7-4ac0-8821-75d0f4fe0773
|
||||
srht_username: nicoco
|
||||
xeps:
|
||||
- note: Participating in groups work, but creation/deletion/moderation is not yet
|
||||
possible from Slidge.
|
||||
- note: Groups are supported, including administration, moderation and creation.
|
||||
number: 45
|
||||
status: partial
|
||||
status: complete
|
||||
- note: Typing notifications only.
|
||||
number: 85
|
||||
status: complete
|
||||
|
|
|
@ -28,6 +28,7 @@ for general info on how to set up an XMPP server component.
|
|||
From [dockerhub](https://hub.docker.com/r/nicocool84/slidge-whatsapp)
|
||||
|
||||
```sh
|
||||
# use ravermeister/slidge-whatsapp for arm64 (thanks raver! <3)
|
||||
docker run docker.io/nicocool84/slidge-whatsapp
|
||||
```
|
||||
|
||||
|
|
4
doap.xml
4
doap.xml
|
@ -47,8 +47,8 @@
|
|||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0045.html" />
|
||||
<xmpp:status>partial</xmpp:status>
|
||||
<xmpp:note>Participating in groups work, but creation/deletion/moderation is not yet possible from Slidge.</xmpp:note>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:note>Groups are supported, including administration, moderation and creation.</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import sys
|
||||
|
||||
from slidge.__main__ import main as slidge_main
|
||||
from slidge import entrypoint
|
||||
|
||||
|
||||
def main() -> None:
|
||||
sys.argv.extend(["--legacy", "slidge_whatsapp"])
|
||||
slidge_main()
|
||||
def main():
|
||||
entrypoint("slidge_whatsapp")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -3,7 +3,7 @@ from datetime import datetime, timezone
|
|||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from slidge.group import LegacyBookmarks, LegacyMUC, LegacyParticipant, MucType
|
||||
from slidge.util.types import Mention
|
||||
from slidge.util.types import Mention, MucAffiliation
|
||||
from slixmpp.exceptions import XMPPError
|
||||
|
||||
from .generated import whatsapp
|
||||
|
@ -88,13 +88,15 @@ class MUC(LegacyMUC[str, str, Participant, str]):
|
|||
if data.Action == whatsapp.GroupParticipantActionRemove:
|
||||
self.remove_participant(participant)
|
||||
else:
|
||||
participant.affiliation = "member"
|
||||
if data.Affiliation == whatsapp.GroupAffiliationAdmin:
|
||||
participant.affiliation = "admin"
|
||||
participant.role = "moderator"
|
||||
elif data.Affiliation == whatsapp.GroupAffiliationOwner:
|
||||
participant.affiliation = "owner"
|
||||
participant.role = "moderator"
|
||||
else:
|
||||
participant.affiliation = "member"
|
||||
participant.role = "participant"
|
||||
|
||||
def replace_mentions(self, t: str):
|
||||
return replace_whatsapp_mentions(
|
||||
|
@ -128,6 +130,29 @@ class MUC(LegacyMUC[str, str, Participant, str]):
|
|||
if self.subject != subject:
|
||||
self.session.whatsapp.SetGroupTopic(self.legacy_id, subject)
|
||||
|
||||
async def on_set_affiliation(
|
||||
self,
|
||||
contact: "Contact", # type:ignore
|
||||
affiliation: MucAffiliation,
|
||||
reason: Optional[str],
|
||||
nickname: Optional[str],
|
||||
):
|
||||
if affiliation == "member":
|
||||
if contact in self._participants_by_contacts:
|
||||
change = "demote"
|
||||
else:
|
||||
change = "add"
|
||||
elif affiliation == "admin":
|
||||
change = "promote"
|
||||
elif affiliation == "outcast" or affiliation == "none":
|
||||
change = "remove"
|
||||
else:
|
||||
raise XMPPError(
|
||||
"bad-request",
|
||||
f"You can't make a participant '{affiliation}' in whatsapp",
|
||||
)
|
||||
self.session.whatsapp.SetAffiliation(self.legacy_id, contact.legacy_id, change)
|
||||
|
||||
|
||||
class Bookmarks(LegacyBookmarks[str, MUC]):
|
||||
session: "Session"
|
||||
|
|
|
@ -453,6 +453,32 @@ func (s *Session) GetGroups() ([]Group, error) {
|
|||
return groups, nil
|
||||
}
|
||||
|
||||
// CreateGroup attempts to create a new WhatsApp group for the given human-readable name and
|
||||
// participant JIDs given.
|
||||
func (s *Session) CreateGroup(name string, participants []string) (Group, error) {
|
||||
if s.client == nil || s.client.Store.ID == nil {
|
||||
return Group{}, fmt.Errorf("Cannot create group for unauthenticated session")
|
||||
}
|
||||
|
||||
var jids []types.JID
|
||||
for _, p := range participants {
|
||||
jid, err := types.ParseJID(p)
|
||||
if err != nil {
|
||||
return Group{}, fmt.Errorf("Could not parse participant JID: %s", err)
|
||||
}
|
||||
|
||||
jids = append(jids, jid)
|
||||
}
|
||||
|
||||
req := whatsmeow.ReqCreateGroup{Name: name, Participants: jids}
|
||||
info, err := s.client.CreateGroup(req)
|
||||
if err != nil {
|
||||
return Group{}, fmt.Errorf("Could not create group: %s", err)
|
||||
}
|
||||
|
||||
return newGroup(s.client, info), nil
|
||||
}
|
||||
|
||||
// GetAvatar fetches a profile picture for the Contact or Group JID given. If a non-empty `avatarID`
|
||||
// is also given, GetAvatar will return an empty [Avatar] instance with no error if the remote state
|
||||
// for the given ID has not changed.
|
||||
|
@ -543,6 +569,23 @@ func (s *Session) SetGroupTopic(resourceID, topic string) error {
|
|||
return s.client.SetGroupTopic(jid, "", "", topic)
|
||||
}
|
||||
|
||||
func (s *Session) SetAffiliation(groupID, participantID string, change whatsmeow.ParticipantChange) ([]types.GroupParticipant, error) {
|
||||
if s.client == nil || s.client.Store.ID == nil {
|
||||
return make([]types.GroupParticipant, 0), fmt.Errorf("Cannot set affiliation for unauthenticated session")
|
||||
}
|
||||
|
||||
groupJID, err := types.ParseJID(groupID)
|
||||
if err != nil {
|
||||
return make([]types.GroupParticipant, 0), fmt.Errorf("Could not parse JID for affiliation change: %s", err)
|
||||
}
|
||||
|
||||
participantJID, err := types.ParseJID(participantID)
|
||||
if err != nil {
|
||||
return make([]types.GroupParticipant, 0), fmt.Errorf("Could not parse JID for affiliation change: %s", err)
|
||||
}
|
||||
return s.client.UpdateGroupParticipants(groupJID, []types.JID{participantJID}, change)
|
||||
}
|
||||
|
||||
// FindContact attempts to check for a registered contact on WhatsApp corresponding to the given
|
||||
// phone number, returning a concrete instance if found; typically, only the contact JID is set. No
|
||||
// error is returned if no contact was found, but any unexpected errors will otherwise be returned
|
||||
|
|
|
@ -443,6 +443,17 @@ class Session(BaseSession[str, Recipient]):
|
|||
"""
|
||||
self.whatsapp.SetAvatar("", await get_bytes_temp(bytes_) if bytes_ else "")
|
||||
|
||||
async def on_create_group(
|
||||
self, name: str, contacts: list[Contact] # type:ignore
|
||||
):
|
||||
"""
|
||||
Creates a WhatsApp group for the given human-readable name and participant list.
|
||||
"""
|
||||
group = self.whatsapp.CreateGroup(
|
||||
name, go.Slice_string([c.legacy_id for c in contacts])
|
||||
)
|
||||
return await self.bookmarks.legacy_id_to_jid_local_part(group.JID)
|
||||
|
||||
async def on_search(self, form_values: dict[str, str]):
|
||||
"""
|
||||
Searches for, and automatically adds, WhatsApp contact based on phone number. Phone numbers
|
||||
|
|
Loading…
Reference in New Issue