Wed, 25 Dec 2024 21:49:48 +0100
add initial code with minimal working contact list and conversations
package de.unixwork.im; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; import java.util.logging.Logger; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.filter.MessageWithBodiesFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.MessageBuilder; import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.RosterEntry; import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; import org.jxmpp.stringprep.XmppStringprepException; public class Xmpp extends Thread { private final XMPPTCPConnectionConfiguration config; private XMPPTCPConnection connection = null; // BlockingQueue for event-driven communication private final BlockingQueue<XmppEvent> eventQueue = new LinkedBlockingQueue<>(); public Xmpp(XMPPTCPConnectionConfiguration xmppConfig) { config = xmppConfig; } // Method to send a message (this will be called from another thread) public void sendMessage(String to, String message, boolean encrypted) { try { XmppMessage event = new XmppMessage(to, message, encrypted); eventQueue.put(event); // Block if the queue is full } catch (InterruptedException e) { Logger.getLogger(Xmpp.class.getName()).log(Level.SEVERE, "Error adding event to queue", e); } } private void connect() throws SmackException, IOException, XMPPException, InterruptedException { connection = new XMPPTCPConnection(config); connection.setUseStreamManagement(false); connection.connect(); connection.login(); } public List<RosterEntry> getRosterItems() throws SmackException.NotLoggedInException, SmackException.NotConnectedException, InterruptedException { try { // Ensure we are connected if (connection != null && connection.isConnected()) { // Get the roster instance Roster roster = Roster.getInstanceFor(connection); // Fetch all roster entries (contacts) roster.reload(); // Add all roster entries to the list ArrayList<RosterEntry> rosterList = new ArrayList<>(16); roster.getEntries().forEach(entry -> rosterList.add(entry)); // Optionally, print the list to verify System.out.println("Roster List: "); for (RosterEntry entry : rosterList) { System.out.println("Contact: " + entry.getUser()); } return rosterList; } else { System.out.println("Not connected to XMPP server."); } } catch (SmackException e) { Logger.getLogger(Xmpp.class.getName()).log(Level.SEVERE, "Error getting roster items", e); } return null; } @Override public void run() { try { connect(); connection.addAsyncStanzaListener((stanza -> { var jid = stanza.getFrom(); if(jid != null) { String body = ((Message)stanza).getBody(); App.getInstance().dispatchMessage(jid, body, true); } }), MessageWithBodiesFilter.INSTANCE); List<RosterEntry> roster = getRosterItems(); if(roster != null) { App.getInstance().setContacts(roster); } while (true) { // Wait for an event (message to send) XmppEvent event = eventQueue.take(); // This will block until an event is available event.exec(this, connection); } } catch (SmackException ex) { Logger.getLogger(Xmpp.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Xmpp.class.getName()).log(Level.SEVERE, null, ex); } catch (XMPPException ex) { Logger.getLogger(Xmpp.class.getName()).log(Level.SEVERE, null, ex); } catch (InterruptedException ex) { Logger.getLogger(Xmpp.class.getName()).log(Level.SEVERE, null, ex); } } } class XmppMessage implements XmppEvent { String to; String message; boolean encrypted; XmppMessage(String to, String message, boolean encrypted) { this.to = to; this.message = message; this.encrypted = encrypted; } public void exec(Xmpp xmpp, XMPPTCPConnection conn) { final Message msg; try { msg = MessageBuilder.buildMessage() .to(to) .setBody(message) .build(); conn.sendStanza(msg); } catch (XmppStringprepException ex) { Logger.getLogger(XmppMessage.class.getName()).log(Level.SEVERE, null, ex); } catch (SmackException.NotConnectedException ex) { Logger.getLogger(XmppMessage.class.getName()).log(Level.SEVERE, null, ex); } catch (InterruptedException ex) { Logger.getLogger(XmppMessage.class.getName()).log(Level.SEVERE, null, ex); } } }