]> cgit.babelmonkeys.de Git - mpdbot.git/blob - src/mpdbot.m
Initial command support
[mpdbot.git] / src / mpdbot.m
1 /*
2  * Copyright (c) 2010, 2011, Jonathan Schleifer <js@webkeks.org>
3  * Copyright (c) 2011, Florian Zeitz <florob@babelmonkeys.de>
4  *
5  * http://cgit.babelmonkeys.de/cgit.cgi/mpdbot/
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice is present in all copies.
10  *
11  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
12  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
15  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
16  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
17  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
18  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
19  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21  * POSSIBILITY OF SUCH DAMAGE.
22  */
23
24 #import <ObjFW/ObjFW.h>
25 #import <ObjXMPP/ObjXMPP.h>
26
27 #import "PEPThread.h"
28
29 #define NS_DISCO_INFO @"http://jabber.org/protocol/disco#info"
30
31 @interface AppDelegate: OFObject <OFApplicationDelegate, XMPPConnectionDelegate>
32 {
33         PEPThread *pepper;
34         MPDConnection *mpdConn;
35 }
36 @end
37
38 OF_APPLICATION_DELEGATE(AppDelegate)
39
40 @implementation AppDelegate
41 - (void)applicationDidFinishLaunching
42 {
43         XMPPConnection *conn;
44
45         OFString *mpd_host;
46         uint16_t mpd_port;
47         OFString *mpd_port_string;
48
49         OFDictionary *environment = [OFApplication environment];
50         OFArray *arguments = [OFApplication arguments];
51
52         conn = [[XMPPConnection alloc] init];
53         [conn addDelegate: self];
54
55         if (arguments.count != 3) {
56                 [of_stdout writeFormat: @"Usage: %@ <server> <user> <passwd>\n",
57                     [OFApplication programName]];
58                 [OFApplication terminateWithStatus: 1];
59         }
60
61         conn.domain = [arguments objectAtIndex: 0];
62         conn.username = [arguments objectAtIndex: 1];
63         conn.password = [arguments objectAtIndex: 2];
64         conn.resource = @"ObjXMPP";
65
66         mpd_host = [environment objectForKey: @"MPD_HOST"];
67         if (mpd_host == nil)
68                 mpd_host = @"localhost";
69
70         mpd_port_string = [environment objectForKey: @"MPD_PORT"];
71         if (mpd_port_string && [mpd_port_string decimalValue] <= UINT16_MAX)
72                 mpd_port = (uint16_t) [mpd_port_string decimalValue];
73         else
74                 mpd_port = 6600;
75
76         mpdConn = [[MPDConnection alloc] initWithHost: mpd_host
77                                                  port: mpd_port];
78         [mpdConn connect];
79
80         @try {
81                 [conn connect];
82                 [conn handleConnection];
83         } @catch (id e) {
84                 [of_stderr writeFormat: @"%@\n", e];
85         }
86 }
87
88 - (void)connectionWasAuthenticated: (XMPPConnection*)conn
89 {
90         [of_stdout writeLine: @"Auth successful"];
91 }
92
93 - (void)connection: (XMPPConnection*)conn
94      wasBoundToJID: (XMPPJID*)jid
95 {
96         XMPPPresence *pres;
97         XMPPIQ *disco;
98         OFString *discoID;
99
100         [of_stdout writeFormat: @"Bound to JID: %@\n", [jid fullJID]];
101
102         pres = [XMPPPresence presence];
103         [pres addPriority: 0];
104         [pres addStatus: @"Hello I'm MPDbot!"];
105         [conn sendStanza: pres];
106
107         discoID = [[conn generateStanzaID] retain];
108         disco = [XMPPIQ IQWithType: @"get"
109                                 ID: discoID];
110         disco.to = [XMPPJID JIDWithString: [[conn JID] bareJID]];
111         [disco addChild: [OFXMLElement
112             elementWithName: @"query"
113                   namespace: NS_DISCO_INFO]];
114
115         [conn       sendIQ: disco
116         withCallbackObject: self
117                   selector: @selector(mpdbot_handleDiscoForConnection:withIQ:)];
118 }
119
120 - (BOOL)mpdbot_handleDiscoForConnection: (XMPPConnection*)conn
121                                  withIQ: (XMPPIQ*)iq
122 {
123         OFXMLElement *query = [iq elementForName: @"query"
124                                        namespace: NS_DISCO_INFO];
125         for (OFXMLElement *identity in [query elementsForName: @"identity"
126                                                     namespace: NS_DISCO_INFO]) {
127                 if ([[[identity attributeForName: @"category"]
128                     stringValue] isEqual: @"pubsub"] &&
129                     [[[identity attributeForName: @"type"] stringValue]
130                     isEqual: @"pep"]) {
131                         pepper = [[PEPThread alloc] initWithObject: conn];
132                         [pepper start];
133
134                         return YES;
135                 }
136         }
137         [of_stderr writeLine: @"Server does NOT support PEP"];
138
139         return NO;
140 }
141
142 -   (void)connection: (XMPPConnection*)conn
143   didReceivePresence: (XMPPPresence*)pres
144 {
145         if ([pres.type isEqual: @"subscribe"]) {
146                 XMPPPresence *answer;
147                 answer = [XMPPPresence presenceWithType: @"subscribed"
148                                                      ID: pres.ID];
149                 answer.to = [XMPPJID JIDWithString: [pres.from bareJID]];
150                 [conn sendStanza: answer];
151         }
152 }
153
154 -  (void)connection: (XMPPConnection*)conn
155   didReceiveMessage: (XMPPMessage*)mesg
156 {
157         if ([mesg.body isEqual: @"pause"]) {
158                 [mpdConn send: @"pause"];
159                 [mpdConn response];
160         }
161 }
162
163 - (void)connectionWasClosed: (XMPPConnection*)conn
164 {
165         [of_stdout writeLine: @"Connection was closed!"];
166 }
167 @end