Пример #1
0
	void Core::Process (QObject *msgObj)
	{
		IMessage *msg = qobject_cast<IMessage*> (msgObj);
		if (msg->GetMessageType () != IMessage::Type::ChatMessage &&
			msg->GetMessageType () != IMessage::Type::MUCMessage)
			return;

		if (msg->GetBody ().isEmpty ())
			return;

		if (msg->GetDirection () == IMessage::Direction::Out &&
				msg->GetMessageType () == IMessage::Type::MUCMessage)
			return;

		const double secsDiff = msg->GetDateTime ().secsTo (QDateTime::currentDateTime ());
		if (msg->GetMessageType () == IMessage::Type::MUCMessage &&
				std::abs (secsDiff) >= 2)
			return;

		ICLEntry *entry = qobject_cast<ICLEntry*> (msg->ParentCLEntry ());
		if (!entry)
		{
			qWarning () << Q_FUNC_INFO
					<< "message's other part doesn't implement ICLEntry"
					<< msg->GetQObject ()
					<< msg->OtherPart ();
			return;
		}
		if (DisabledIDs_.contains (entry->GetEntryID ()))
			return;

		const auto acc = entry->GetParentAccount ();

		QVariantMap data;
		data ["EntryID"] = entry->GetEntryID ();
		data ["AccountID"] = acc->GetAccountID ();
		data ["DateTime"] = msg->GetDateTime ();
		data ["Direction"] = msg->GetDirection () == IMessage::Direction::In ? "IN" : "OUT";
		data ["Body"] = msg->GetBody ();
		data ["OtherVariant"] = msg->GetOtherVariant ();
		data ["Type"] = static_cast<int> (msg->GetMessageType ());
		data ["EscapePolicy"] = msg->GetEscapePolicy () == IMessage::EscapePolicy::Escape ? "Esc" : "NEs";

		if (const auto irtm = qobject_cast<IRichTextMessage*> (msgObj))
			data ["RichBody"] = irtm->GetRichBody ();

		if (entry->GetEntryType () == ICLEntry::EntryType::PrivateChat)
		{
			const auto parent = entry->GetParentCLEntry ();
			data ["VisibleName"] = parent->GetEntryName () + "/" + entry->GetEntryName ();
		}
		else
			data ["VisibleName"] = entry->GetEntryName ();

		QMetaObject::invokeMethod (StorageThread_->GetStorage (),
				"addMessage",
				Qt::QueuedConnection,
				Q_ARG (QVariantMap, data));
	}
Пример #2
0
	void Core::Process (QObject *msgObj)
	{
		IMessage *msg = qobject_cast<IMessage*> (msgObj);
		if (msg->GetMessageType () != IMessage::MTChatMessage &&
			msg->GetMessageType () != IMessage::MTMUCMessage)
			return;
		if (msg->GetBody ().isEmpty ())
			return;
		if (msg->GetDirection () == IMessage::DOut &&
				msg->GetMessageType () == IMessage::MTMUCMessage)
			return;
		
		ICLEntry *entry = qobject_cast<ICLEntry*> (msg->ParentCLEntry ());
		if (!entry)
		{
			qWarning () << Q_FUNC_INFO
					<< "message's other part doesn't implement ICLEntry"
					<< msg->GetObject ()
					<< msg->OtherPart ();
			return;
		}
		if (DisabledIDs_.contains (entry->GetEntryID ()))
			return;

		IAccount *acc = qobject_cast<IAccount*> (entry->GetParentAccount ());
		if (!acc)
		{
			qWarning () << Q_FUNC_INFO
					<< "message's account doesn't implement IAccount"
					<< entry->GetParentAccount ();
			return;
		}
		
		QVariantMap data;
		data ["EntryID"] = entry->GetEntryID ();
		data ["VisibleName"] = entry->GetEntryName ();
		data ["AccountID"] = acc->GetAccountID ();
		data ["DateTime"] = msg->GetDateTime ();
		data ["Direction"] = msg->GetDirection () == IMessage::DIn ? "IN" : "OUT";
		data ["Body"] = msg->GetBody ();
		data ["OtherVariant"] = msg->GetOtherVariant ();
		data ["MessageType"] = static_cast<int> (msg->GetMessageType ());
		
		QMetaObject::invokeMethod (StorageThread_->GetStorage (),
				"addMessage",
				Qt::QueuedConnection,
				Q_ARG (QVariantMap, data));
	}
Пример #3
0
	void Plugin::RequestLastMessages (QObject *entryObj, int num)
	{
		ICLEntry *entry = qobject_cast<ICLEntry*> (entryObj);
		if (!entry)
		{
			qWarning () << Q_FUNC_INFO
					<< entryObj
					<< "doesn't implement ICLEntry";
			return;
		}

		if (entry->GetEntryType () != ICLEntry::ETChat)
			return;

		IAccount *account = qobject_cast<IAccount*> (entry->GetParentAccount ());
		if (!account)
		{
			qWarning () << Q_FUNC_INFO
					<< entry->GetParentAccount ()
					<< "doesn't implement IAccount";
			return;
		}

		const QString& accId = account->GetAccountID ();
		const QString& entryId = entry->GetEntryID ();
		Core::Instance ()->GetChatLogs (accId, entryId, 0, num);

		RequestedLogs_ [accId] [entryId] = entryObj;
	}
Пример #4
0
	void Plugin::hookEntryStatusChanged (IHookProxy_ptr, QObject *entryObj, QString)
	{
		if (!IsGoodEntry (entryObj))
			return;

		ICLEntry *entry = qobject_cast<ICLEntry*> (entryObj);
		const QString& id = entry->GetEntryID ();
		const EntryStatus& status = entry->GetStatus ();

		if (!LastState_.contains (id))
		{
			LastState_ [id] = status.State_;
			return;
		}

		const State oldState = LastState_ [id];
		LastState_ [id] = status.State_;

		switch (oldState)
		{
		case SOffline:
		case SProbe:
		case SError:
		case SInvalid:
		case SConnecting:
			return;
		case SOnline:
			LastAvailable_ [id] = QDateTime::currentDateTime ();
		default:
			LastOnline_ [id] = QDateTime::currentDateTime ();
			ScheduleSave ();
		}
	}
Пример #5
0
	bool CLModel::TryDropFile (const QMimeData* mime, const QModelIndex& parent)
	{
		if (parent.data (Core::CLREntryType).value<Core::CLEntryType> () != Core::CLETContact)
			return false;

		QObject *entryObj = parent.data (Core::CLREntryObject).value<QObject*> ();
		ICLEntry *entry = qobject_cast<ICLEntry*> (entryObj);
		if (entry->Variants ().isEmpty ())
			return false;

		IAccount *acc = qobject_cast<IAccount*> (entry->GetParentAccount ());
		ITransferManager *mgr = qobject_cast<ITransferManager*> (acc->GetTransferManager ());
		if (!mgr)
			return false;

		const QList<QUrl>& urls = mime->urls ();
		if (urls.isEmpty ())
			return false;

		QString text;
		if (urls.size () > 2)
			text = tr ("Are you sure you want to send %n files to %1?", 0, urls.size ())
					.arg (entry->GetEntryName ());
		else
		{
			QStringList list;
			Q_FOREACH (const QUrl& url, urls)
				list << QFileInfo (url.path ()).fileName ();
			text = tr ("Are you sure you want to send %1 to %2?")
					.arg ("<em>" + list.join (", ") + "</em>")
					.arg (entry->GetEntryName ());
		}
		if (QMessageBox::question (0,
					"LeechCraft",
					text,
					QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
			return false;

		Q_FOREACH (const QUrl& url, urls)
		{
			const QString& path = url.toLocalFile ();

			if (!QFileInfo (path).exists ())
				continue;

			QObject *job = mgr->SendFile (entry->GetEntryID (),
					entry->Variants ().first (), path);
			Core::Instance ().GetTransferJobManager()->HandleJob (job);
		}

		return true;
	}
Пример #6
0
void Plugin::hookFormatBodyEnd (IHookProxy_ptr proxy,
                                QObject *chatTab, QString body, QObject *msgObj)
{
    IMessage *msg = qobject_cast<IMessage*> (msgObj);
    if (msg->GetDirection () != IMessage::DIn ||
            msg->GetMessageType () != IMessage::MTChatMessage)
        return;

    ICLEntry *other = qobject_cast<ICLEntry*> (msg->OtherPart ());
    if (!other->GetEntryID ().contains ("*****@*****.**"))
        return;

    proxy->SetValue ("body", FormatBody (body));
}
Пример #7
0
	void Plugin::hookTooltipBeforeVariants (IHookProxy_ptr proxy, QObject *entryObj)
	{
		if (!IsGoodEntry (entryObj))
			return;

		ICLEntry *entry = qobject_cast<ICLEntry*> (entryObj);
		const QString& id = entry->GetEntryID ();

		QString addition;

		const State curState = entry->GetStatus ().State_;

		if (curState != SOnline)
		{
			const QDateTime& avail = LastAvailable_.value (id);
			if (avail.isValid ())
				addition += tr ("Was available: %1")
					.arg (avail.toString ());
		}

		if (curState == SOffline ||
				curState == SError ||
				curState == SInvalid)
		{
			const QDateTime& online = LastOnline_.value (id);
			if (LastOnline_.contains (id))
			{
				if (!addition.isEmpty ())
					addition += "<br/>";
				addition += tr ("Was online: %1")
					.arg (online.toString ());
			}
		}

		if (addition.isEmpty ())
			return;

		const QString& tip = proxy->GetValue ("tooltip").toString ();
		proxy->SetValue ("tooltip", tip + "<br/><br/>" + addition + "<br/>");
	}
Пример #8
0
	void Plugin::hookFormatBodyEnd (IHookProxy_ptr proxy,
			QObject*, QString body, QObject *msgObj)
	{
		IMessage *msg = qobject_cast<IMessage*> (msgObj);
		if (msg->GetDirection () != IMessage::DIn ||
				msg->GetMessageType () != IMessage::MTChatMessage)
			return;

		ICLEntry *other = qobject_cast<ICLEntry*> (msg->OtherPart ());
		if (!other)
		{
			qWarning () << Q_FUNC_INFO
					<< "NULL other part for message"
					<< msgObj
					<< msg->GetBody ();
			return;
		}

		if (!other->GetEntryID ().contains ("*****@*****.**"))
			return;

		proxy->SetValue ("body", FormatBody (body));
	}
Пример #9
0
	bool Plugin::ShouldHandle (QObject* msgObj,
			IMessage::Direction direction, IMessage::Type type)
	{
		IMessage *msg = qobject_cast<IMessage*> (msgObj);

		if (!msg)
		{
			qWarning () << Q_FUNC_INFO
				<< "unable to cast"
				<< msgObj
				<< "to IMessage";
			return false;
		}

		if (msg->GetDirection () != direction ||
			msg->GetMessageType () != type)
		{
			return false;
		}

		ICLEntry *other = qobject_cast<ICLEntry*> (msg->OtherPart ());

		if (!other)
		{
			qWarning () << Q_FUNC_INFO
				<< "unable to cast"
				<< msg->OtherPart ()
				<< "to ICLEntry";
			return false;
		}

		if (!other->GetEntryID ().contains ("*****@*****.**"))
			return false;

		return true;

	}
Пример #10
0
	void Plugin::hookMessageWillCreated (LeechCraft::IHookProxy_ptr proxy,
			QObject *chatTab, QObject *entry, int, QString)
	{
		ICLEntry *other = qobject_cast<ICLEntry*> (entry);

		if (!other)
		{
			qWarning () << Q_FUNC_INFO
				<< "unable to cast"
				<< entry
				<< "to ICLEntry";
			return;
		}

		if (!other->GetEntryID ().contains ("*****@*****.**"))
			return;

		QString text = proxy->GetValue ("text").toString ();

		Typo typos[] = {
			Typo (text, QString::fromUtf8 ("^!\\s+[#№]{2,}(\\d+)"), QString ("! #\\1")),
			Typo (text, "^!\\s+(\\d+)", QString ("! #\\1")),
			Typo (text, QString::fromUtf8 ("^![#№](\\d+)"), QString ("! #\\1")),
			Typo (text, "^!(\\d+)", QString ("! #\\1")),
			Typo (text, QString::fromUtf8 ("^[SЫ]\\s+[#№]{2,}(\\d+)"), QString ("S #\\1")),
			Typo (text, QString::fromUtf8 ("^[SЫ]\\s+(\\d+)"), QString ("S #\\1")),
			Typo (text, QString::fromUtf8 ("^[SЫ][#№](\\d+)"), QString ("S #\\1")),
			Typo (text, QString::fromUtf8 ("^[SЫ](\\d+)"), QString ("S #\\1")),
			Typo (text, QString::fromUtf8 ("^Ы [#№](\\d+)"), QString ("S #\\1")),
			Typo (text, QString::fromUtf8 ("^ЗЬ\\s+@(.*)"), QString ("PM @\\1")),
			Typo (text, "^(\\d+)\\s+(.*)", QString ("#\\1 \\2")),
			Typo (text, "^(\\d+/\\d+)\\s+(.*)", QString ("#\\1 \\2")),
			Typo (text, QString::fromUtf8 ("^№\\+$"), QString ("#+")),
			Typo (text, QString::fromUtf8 ("^\"$"), QString ("@")),
			Typo (text, QString::fromUtf8 ("^В\\s?Д$"), QString ("D L")),
			Typo (text, QString::fromUtf8 ("$Ы^"), QString ("S")),
			Typo (text, QString::fromUtf8 ("^[UГ]\\s+[#№]{2,}(\\d+)"), QString ("U #\\1")),
			Typo (text, QString::fromUtf8 ("^[UГ]\\s+(\\d+)"), QString ("U #\\1")),
			Typo (text, QString::fromUtf8 ("^[UГ][#№](\\d+)"), QString ("U #\\1")),
			Typo (text, QString::fromUtf8 ("^[UГ](\\d+)"), QString ("U #\\1")),
			Typo (text, QString::fromUtf8 ("^Г [#№](\\d+)"), QString ("U #\\1")),
			Typo (text, QString::fromUtf8 ("^В [#№](\\d+)"), QString ("D #\\1")),
			Typo (text, QString::fromUtf8 ("^[DВ][#№](\\d+)"), QString ("D #\\1")),
			Typo (text, QString::fromUtf8 ("^[DВ](\\d+)"), QString ("D #\\1")),
			Typo (text, QString::fromUtf8 ("^РУДЗ$"), QString ("HELP")),
			Typo (text, QString::fromUtf8 ("^ДЩПШТ$"), QString ("LOGIN")),
			Typo (text, QString::fromUtf8 ("^ЩТ(\\+?)$"), QString ("ON\\1")),
			Typo (text, QString::fromUtf8 ("^ЩАА$"), QString ("OFF")),
			Typo (text, QString::fromUtf8 ("^ИД(\\s?)"), QString ("BL\\1")),
			Typo (text, QString::fromUtf8 ("^ЦД(\\s?)"), QString ("WL\\1")),
			Typo (text, QString::fromUtf8 ("^ШТМШЕУ "), QString ("INVITE ")),
			Typo (text, QString::fromUtf8 ("^МСФКВ$"), QString ("VCARD")),
			Typo (text, QString::fromUtf8 ("^ЗШТП$"), QString ("PING")),
			Typo (text, QString::fromUtf8 ("^№+$"), [] (QString str) { return str.replace ("№", "#"); })
		};

		for (int i = 0; i < static_cast<int> (sizeof (typos) / sizeof (Typo)); ++i)
		{
			Typo typo = typos [i];

			if (!typo.Done ())
				continue;

			QSettings settings (QCoreApplication::organizationName (),
				QCoreApplication::applicationName () + "_AzothJuick");
			QWidget* parent = qobject_cast<QWidget*> (chatTab);
			QString correction = typo.Correction ();
			bool askForCorrection = settings.value ("AskForCorrection", true).toBool ();

			if (!parent)
			{
				qWarning () << Q_FUNC_INFO
					<< "unable to cast"
					<< chatTab
					<< "to QWidget";
				return;
			}

			QMessageBox msgbox (QMessageBox::Question,
					tr ("Fix typo?"),
					tr ("Did you mean <em>%1</em> instead of <em>%2</em>?")
						.arg (correction)
						.arg (text),
					QMessageBox::NoButton,
					parent);
			msgbox.addButton (QMessageBox::Yes);
			QPushButton *always = msgbox.addButton (tr ("Always"), QMessageBox::YesRole);
			msgbox.addButton (QMessageBox::No);

			if (!askForCorrection || msgbox.exec () != QMessageBox::No)
			{
				proxy->SetValue ("text", correction);
				if (msgbox.clickedButton () == always)
					settings.setValue ("AskForCorrection", false);
			}
			break;
		}
	}
Пример #11
0
	void Plugin::hookMessageWillCreated (LeechCraft::IHookProxy_ptr proxy,
			QObject*, QObject *entry, int, QString)
	{
		ICLEntry *other = qobject_cast<ICLEntry*> (entry);
		if (!other)
		{
			qWarning () << Q_FUNC_INFO
				<< "unable to cast"
				<< entry
				<< "to ICLEntry";
			return;
		}

		QString text = proxy->GetValue ("text").toString ();

		const int maxLines = XmlSettingsManager::Instance ()
				.property ("LineCount").toInt ();
		const int maxSymbols = XmlSettingsManager::Instance ()
				.property ("SymbolCount").toInt ();
		if (text.size () < maxSymbols &&
				text.count ('\n') + 1 < maxLines)
			return;

		QByteArray propName;
		switch (other->GetEntryType ())
		{
		case ICLEntry::ETChat:
			propName = "EnableForNormalChats";
			break;
		case ICLEntry::ETMUC:
			propName = "EnableForMUCChats";
			break;
		case ICLEntry::ETPrivateChat:
			propName = "EnableForPrivateChats";
			break;
		default:
			return;
		}

		if (!XmlSettingsManager::Instance ().property (propName).toBool ())
			return;

		QSettings settings (QCoreApplication::organizationName (),
				QCoreApplication::applicationName () + "_Azoth_Autopaste");
		settings.beginGroup ("SavedChoices");
		settings.beginGroup (other->GetEntryID ());
		auto guard = std::shared_ptr<void> (nullptr,
				[&settings] (void*) -> void
				{
					settings.endGroup ();
					settings.endGroup ();
				});

		PasteDialog dia;

		dia.SetCreatorName (settings.value ("Service").toString ());
		dia.SetHighlight (static_cast<Highlight> (settings.value ("Highlight").toInt ()));

		dia.exec ();

		switch (dia.GetChoice ())
		{
		case PasteDialog::Cancel:
			proxy->CancelDefault ();
		case PasteDialog::No:
			return;
		case PasteDialog::Yes:
		{
			auto service = dia.GetCreator () (entry);
			service->Paste ({ Proxy_->GetNetworkAccessManager (), text, dia.GetHighlight () });
			proxy->CancelDefault ();

			settings.setValue ("Service", dia.GetCreatorName ());
			settings.setValue ("Highlight", static_cast<int> (dia.GetHighlight ()));
		}
		}
	}