From: Florian Zeitz Date: Fri, 8 Jul 2011 18:07:41 +0000 (+0200) Subject: Initial commit X-Git-Url: https://cgit.babelmonkeys.de/?a=commitdiff_plain;h=ebdb0334e69757c87ff7bcb26f853e86d9ca5c3d;p=mpdbot.git Initial commit --- ebdb0334e69757c87ff7bcb26f853e86d9ca5c3d diff --git a/PEPThread.h b/PEPThread.h new file mode 100644 index 0000000..5e6cfb8 --- /dev/null +++ b/PEPThread.h @@ -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 index 0000000..9aa58ad --- /dev/null +++ b/PEPThread.m @@ -0,0 +1,95 @@ +#import +#import + +#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 index 0000000..ea84079 --- /dev/null +++ b/mpdbot.m @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2010, 2011, Jonathan Schleifer + * Copyright (c) 2011, Florian Zeitz + * + * 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 + +#import +#import + +#import "PEPThread.h" + +#define NS_DISCO_INFO @"http://jabber.org/protocol/disco#info" + +@interface AppDelegate: OFObject +#ifdef OF_HAVE_OPTIONAL_PROTOCOLS + +#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