summaryrefslogtreecommitdiffstats
blob: 1578e3425c0aad228fcab9a7cb59811448b956e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * Copyright (c) 2011 Kevin Smith
 * Licensed under the GNU General Public License v3.
 * See Documentation/Licenses/GPLv3.txt for more information.
 */

#include <Swiftob/Swiftob.h>

#include <string>
#include <iostream>
#include <boost/bind.hpp>

#include <Swiften/JID/JID.h>
#include <Swiften/Base/String.h>
#include <Swiften/Presence/PresenceSender.h>

#include <Swiftob/Users.h>
#include <Swiftob/Storage.h>


po::options_description Swiftob::getOptionsDescription() {
	po::options_description result("Options");
	result.add_options()
		("path", po::value<std::string>(), "Configuration folder")
		("help", "produce help message")
		("init", "Reset everything (Really, everything, be careful, you only want to use this on first run).")
		("jid", po::value<std::string>(), "JID to use")
		("password", po::value<std::string>(), "password")
		("initial-owner", po::value<std::string>(), "Initial bot owner (JID)")
		;
	return result;
}

Swiftob::Swiftob(const po::variables_map& options) : options_(options), networkFactories_(&eventLoop_), quitting_(false) {
	path_ = options["path"].as<std::string>();
	client_ = new Swift::Client(Swift::JID(options["jid"].as<std::string>()), options["password"].as<std::string>(), &networkFactories_);
	storage_ = new Storage(boost::filesystem::path(path_) / "settings.txt");
	mucs_ = NULL;
	users_ = NULL;
	commands_ = NULL;
	lua_ = NULL;
	init();
	client_->onConnected.connect(boost::bind(&Swiftob::handleConnected, this));
	client_->onDisconnected.connect(boost::bind(&Swiftob::handleDisconnected, this, _1));
	client_->onMessageReceived.connect(boost::bind(&Swiftob::handleMessageReceived, this, _1));
	if (options_.count("init") > 0) {

	} else if (options_.count("jid") > 0 || options_.count("password") > 0 || options_.count("initial-owner") == 0) {
		std::cout << "Ignoring initial config options without --initial" << std::endl;
	}
	client_->setAlwaysTrustCertificates();
	client_->setSoftwareVersion("Swiftob", "pregit", "");
	client_->connect();
	eventLoop_.run();
}

void Swiftob::init() {
	delete mucs_;
	mucs_ = new MUCs(client_, storage_);
	delete users_;
	users_ = new Users(client_, mucs_);
	delete commands_;
	commands_ = new Commands(users_, client_, storage_, mucs_);
	commands_->onRestartRequested.connect(boost::bind(&Swiftob::handleRestartRequested, this));
	delete lua_;
	lua_ = new LuaCommands(commands_, path_, client_, networkFactories_.getTimerFactory(), mucs_);
}

void Swiftob::handleRestartRequested() {
	client_->disconnect();
	init();
}

void Swiftob::handleConnected() {
	std::cout << "Connected" << std::endl;
	if (options_.count("init") > 0) {}{ /* FIXME: Not ready for persistence yet*/
		users_->clearAll();
		users_->addUser(Users::User(Swift::JID(options_["initial-owner"].as<std::string>()), Users::User::Owner));
	}
	Swift::Presence::ref presence(new Swift::Presence());
	presence->setStatus("Online and botty");
	client_->getPresenceSender()->sendPresence(presence);
}

void Swiftob::handleDisconnected(const boost::optional<Swift::ClientError>& /*error*/) {
	std::cout << "Disconnected" << std::endl;
	/* FIXME: check if last connect was more than a minute ago. If so, go ahead and connect, if not then wait a minute before connecting.*/
	if (quitting_) {
		eventLoop_.stop();
	} else {
		client_->connect();
	}
}

void Swiftob::handleMessageReceived(Swift::Message::ref message) {
	Swift::Message::Type type = message->getType();
	if (type == Swift::Message::Error || type == Swift::Message::Headline) {
		std::cout << "Ignoring typed message" << std::endl;
		return;
	}
	std::string body = message->getBody();
	std::cout << "Got message with body " << body << std::endl;
	if (body.size() == 0) {
		std::cout << "Not handling empty body" << std::endl;
		return;
	}

	/* Run through any full-message listeners */
	commands_->runListeners(message);

	/*Convert body into !command if it's not a MUC, and it misses the bang*/
	std::string bangBody(body);
	if (type != Swift::Message::Groupchat && body[0] != '!') {
		bangBody = "!" + body;
	}
	std::cout << "After banging, body is " << bangBody << std::endl;
	std::pair<std::string, std::string> split = Swift::String::getSplittedAtFirst(bangBody, ' ');
	std::string commandName(split.first);
	commandName = Swift::String::getSplittedAtFirst(commandName, '!').second;
	/*FIXME: remove leading bang in commandName*/
	if (commands_->hasCommand(commandName)) {
		std::cout << "Matched command " << commandName << std::endl;
		commands_->runCommand(commandName, split.second, message);
	}
}

Swiftob::~Swiftob() {
	delete lua_;
	delete commands_;
	delete storage_;
	delete users_;
	delete mucs_;
	delete client_;
}

int Swiftob::exec() {
	return 0;
}