]> cgit.babelmonkeys.de Git - mpdbot.git/commitdiff
Initial commit
authorFlorian Zeitz <florob@babelmonkeys.de>
Fri, 8 Jul 2011 18:07:41 +0000 (20:07 +0200)
committerFlorian Zeitz <florob@babelmonkeys.de>
Fri, 8 Jul 2011 18:07:41 +0000 (20:07 +0200)
PEPThread.h [new file with mode: 0644]
PEPThread.m [new file with mode: 0644]
mpdbot.m [new file with mode: 0644]

diff --git a/PEPThread.h b/PEPThread.h
new file mode 100644 (file)
index 0000000..5e6cfb8
--- /dev/null
@@ -0,0 +1,3 @@
+@interface PEPThread: OFThread
+- (OFMutableDictionary*)MPD_responeFromSocket: (OFTCPSocket*)sock;
+@end
diff --git a/PEPThread.m b/PEPThread.m
new file mode 100644 (file)
index 0000000..9aa58ad
--- /dev/null
@@ -0,0 +1,95 @@
+#import <ObjFW/ObjFW.h>
+#import <ObjXMPP/ObjXMPP.h>
+
+#import "PEPThread.h"
+
+#define NS_PUBSUB @"http://jabber.org/protocol/pubsub"
+#define NS_TUNE @"http://jabber.org/protocol/tune"
+
+@implementation PEPThread: OFThread
+- (OFMutableDictionary*)MPD_responeFromSocket: (OFTCPSocket*)sock
+{
+       OFString *answer;
+       OFMutableDictionary *response = [OFMutableDictionary dictionary];
+       while ((answer = [sock readLine]) && ![answer hasPrefix: @"OK"]) {
+               size_t index;
+               index = [answer indexOfFirstOccurrenceOfString: @":"];
+               if (index == OF_INVALID_INDEX)
+                       continue;
+               [response setObject: [answer substringFromIndex: index + 2
+                                                       toIndex: answer.length]
+                            forKey: [answer substringFromIndex: 0
+                                                       toIndex: index]];
+       }
+
+       return response;
+}
+
+- (id)main
+{
+       OFTCPSocket *sock = [OFTCPSocket socket];
+       [sock connectToHost: @"localhost"
+                      port: 6600];
+       [self MPD_responeFromSocket: sock];
+       while (1) {
+               OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
+               OFMutableDictionary *response;
+               OFString *answer;
+               XMPPIQ *tuneIQ = [XMPPIQ IQWithType: @"set"
+                                                ID: [object generateStanzaID]];
+               OFXMLElement *pubsub = [OFXMLElement
+                   elementWithName: @"pubsub"
+                         namespace: NS_PUBSUB];
+               [tuneIQ addChild: pubsub];
+               OFXMLElement *publish = [OFXMLElement 
+                   elementWithName: @"publish"
+                         namespace: NS_PUBSUB];
+               [publish addAttributeWithName: @"node"
+                                 stringValue: NS_TUNE];
+               [pubsub addChild: publish];
+               OFXMLElement *item = [OFXMLElement elementWithName: @"item"
+                                                        namespace: NS_PUBSUB];
+               [publish addChild: item];
+               OFXMLElement *tune = [OFXMLElement elementWithName: @"tune"
+                                                        namespace: NS_TUNE];
+               [item addChild: tune];
+               [sock writeLine: @"status"];
+               response = [self MPD_responeFromSocket: sock];
+               if ([[response objectForKey: @"state"] isEqual: @"play"]) {
+                       [sock writeLine: @"currentsong"];
+                       response = [self MPD_responeFromSocket: sock];
+                       if ((answer = [response objectForKey: @"Artist"]))
+                               [tune addChild: [OFXMLElement
+                                   elementWithName: @"artist"
+                                         namespace: NS_TUNE
+                                       stringValue: answer]];
+                       if ((answer = [response objectForKey: @"Time"]))
+                               [tune addChild: [OFXMLElement
+                                   elementWithName: @"length"
+                                         namespace: NS_TUNE
+                                       stringValue: answer]];
+                       if ((answer = [response objectForKey: @"Album"]))
+                               [tune addChild: [OFXMLElement
+                                   elementWithName: @"source"
+                                         namespace: NS_TUNE
+                                       stringValue: answer]];
+                       if ((answer = [response objectForKey: @"Title"]))
+                               [tune addChild: [OFXMLElement
+                                   elementWithName: @"title"
+                                         namespace: NS_TUNE
+                                       stringValue: answer]];
+                       if ((answer = [response objectForKey: @"Track"]))
+                               [tune addChild: [OFXMLElement
+                                   elementWithName: @"track"
+                                         namespace: NS_TUNE
+                                       stringValue: answer]];
+               }
+               [object sendStanza: tuneIQ];
+               [sock writeLine: @"idle player"];
+               [self MPD_responeFromSocket: sock];
+               [pool release];
+       }
+
+       return nil;
+}
+@end
diff --git a/mpdbot.m b/mpdbot.m
new file mode 100644 (file)
index 0000000..ea84079
--- /dev/null
+++ b/mpdbot.m
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2010, 2011, Jonathan Schleifer <js@webkeks.org>
+ * Copyright (c) 2011, Florian Zeitz <florob@babelmonkeys.de>
+ *
+ * https://webkeks.org/hg/objxmpp/
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+
+#import <ObjFW/ObjFW.h>
+#import <ObjXMPP/ObjXMPP.h>
+
+#import "PEPThread.h"
+
+#define NS_DISCO_INFO @"http://jabber.org/protocol/disco#info"
+
+@interface AppDelegate: OFObject
+#ifdef OF_HAVE_OPTIONAL_PROTOCOLS
+    <OFApplicationDelegate, XMPPConnectionDelegate>
+#endif
+
+OFString *discoID;
+PEPThread *pepper;
+@end
+
+OF_APPLICATION_DELEGATE(AppDelegate)
+
+@implementation AppDelegate
+- (void)applicationDidFinishLaunching
+{
+       XMPPConnection *conn;
+       OFArray *arguments = [OFApplication arguments];
+
+       conn = [[XMPPConnection alloc] init];
+       [conn setDelegate: self];
+
+       if ([arguments count] != 3) {
+               of_log(@"Invalid count of command line arguments!");
+               [OFApplication terminateWithStatus: 1];
+       }
+
+       [conn setDomain: [arguments objectAtIndex: 0]];
+       [conn setUsername: [arguments objectAtIndex: 1]];
+       [conn setPassword: [arguments objectAtIndex: 2]];
+       [conn setResource: @"ObjXMPP"];
+
+       @try {
+               [conn connect];
+               [conn handleConnection];
+       } @catch (id e) {
+               of_log(@"%@", e);
+       }
+}
+
+- (void)connectionWasAuthenticated: (XMPPConnection*)conn
+{
+       of_log(@"Auth successful");
+}
+
+- (void)connection: (XMPPConnection*)conn
+     wasBoundToJID: (XMPPJID*)jid
+{
+       XMPPPresence *pres;
+       XMPPIQ *disco;
+
+       of_log(@"Bound to JID: %@", [jid fullJID]);
+
+       pres = [XMPPPresence presence];
+       [pres addPriority: 0];
+       [pres addStatus: @"Hello I'm MPDbot!"];
+       [conn sendStanza: pres];
+
+       discoID = [[conn generateStanzaID] retain];
+       disco = [XMPPIQ IQWithType: @"get"
+                               ID: discoID];
+       disco.to = [XMPPJID JIDWithString: [[conn JID] bareJID]];
+       [disco addChild: [OFXMLElement
+       elementWithName: @"query"
+             namespace: NS_DISCO_INFO]];
+
+       [conn sendStanza: disco];
+}
+
+- (BOOL)connection: (XMPPConnection*)conn
+      didReceiveIQ: (XMPPIQ*)iq
+{
+       OFXMLElement *query = [iq elementForName: @"query"
+                                      namespace: NS_DISCO_INFO];
+       if ([[iq ID] isEqual: discoID]) {
+               for (OFXMLElement *identity
+                   in [query elementsForName: @"identity"
+                                   namespace: NS_DISCO_INFO]) {
+                       if ([[[identity attributeForName: @"category"]
+                           stringValue] isEqual: @"pubsub"] &&
+                           [[[identity attributeForName: @"type"] stringValue]
+                           isEqual: @"pep"]) {
+                               pepper = [[PEPThread alloc]
+                                   initWithObject: conn];
+                               [pepper start];
+                               return YES;
+                       }
+               }
+       }
+
+       return NO;
+}
+
+-  (void)connection: (XMPPConnection*)conn
+  didReceiveMessage: (XMPPMessage*)msg
+{
+       of_log(@"Message: %@", msg);
+}
+
+-   (void)connection: (XMPPConnection*)conn
+  didReceivePresence: (XMPPPresence*)pres
+{
+       of_log(@"Presence: %@", pres);
+}
+
+- (void)connectionWasClosed: (XMPPConnection*)conn
+{
+       of_log(@"Connection was closed!");
+}
+@end