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)); }
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)); }
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; }
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 (); } }
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; }
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)); }
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/>"); }
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)); }
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; }
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; } }
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 ())); } } }