void ChatUrls::openChannelUrl(const QUrl &url) { QStringList actions = ChatUrls::actions(url); if (actions.isEmpty()) return; ClientChannel channel = ChatUrls::channel(url); if (!channel) return; QString action = actions.first(); if (action == LS("open")) { ChatNotify::start(Notify::OpenChannel, channel->id()); } else if (action == LS("info")) { ChatNotify::start(Notify::OpenInfo, channel->id()); } else if (action == LS("insert")) { ChatNotify::start(Notify::InsertText, QChar(QChar::Nbsp) + QString(LS("<a class=\"nick color-%1\" href=\"%2\">%3</a>")) .arg(Gender::colorToString(channel->gender().color())) .arg(url.toString()) .arg(Qt::escape(channel->name())) + QChar(QChar::Nbsp)); } else if (action == LS("edit")) { if (actions.size() == 1) return; if (actions.at(1) == LS("topic") && channel->type() == SimpleID::ChannelId) ChatNotify::start(Notify::EditTopic, channel->id()); } }
ChannelTab::ChannelTab(ClientChannel channel, TabWidget *parent) : ChannelBaseTab(channel, LS("channel"), parent) { m_userView = new UserView(channel, this); m_leftLayout = new QVBoxLayout(this); m_leftLayout->addWidget(m_chatView); m_leftLayout->setMargin(0); m_leftLayout->setSpacing(0); QWidget *left = new QWidget(this); left->setLayout(m_leftLayout); m_splitter = new QSplitter(this); m_splitter->addWidget(left); m_splitter->addWidget(m_userView); m_splitter->setStretchFactor(0, 1); m_splitter->setStretchFactor(1, 1); m_splitter->setOpaqueResize(false); QVBoxLayout *mainLay = new QVBoxLayout(this); mainLay->addWidget(m_splitter); mainLay->setMargin(0); mainLay->setSpacing(0); setText(channel->name()); connect(ChatClient::channels(), SIGNAL(channels(QList<QByteArray>)), SLOT(channels(QList<QByteArray>))); connect(ChatClient::channels(), SIGNAL(joined(QByteArray,QByteArray)), SLOT(joined(QByteArray,QByteArray))); connect(ChatClient::channels(), SIGNAL(part(QByteArray,QByteArray)), SLOT(part(QByteArray,QByteArray))); connect(ChatClient::channels(), SIGNAL(quit(QByteArray,bool)), SLOT(quit(QByteArray,bool))); connect(ChatClient::channels(), SIGNAL(channel(QByteArray)), SLOT(channel(QByteArray))); m_chatView->add(ServiceMessage::joined(ChatClient::id())); }
/*! * Отправка обновлённой информации о себе. */ ChannelPacket ChannelNotice::update(ClientChannel channel) { ChannelPacket packet(new ChannelNotice(channel->id(), channel->id(), CHANNELS_UPDATE_CMD, DateTime::utc())); packet->setText(channel->name()); packet->gender = channel->gender().raw(); packet->channelStatus = channel->status().value(); return packet; }
ChannelPacket ChannelNotice::info(ClientChannel channel, qint64 date) { ChannelPacket packet(new ChannelNotice(channel->id(), channel->id(), CHANNELS_INFO_CMD, date ? date : DateTime::utc())); packet->setDirection(Server2Client); packet->setText(channel->name()); packet->gender = channel->gender().raw(); packet->channelStatus = channel->status().value(); return packet; }
/*! * Создание или повторная инициализация вкладки канала. * * \param id Идентификатор канала. * \param create \b true если необходимо создать канал. * \param show \b true если необходимо выбрать эту вкладку. * * \return Возвращает указатель на вкладку или 0 в случае ошибки. */ ChannelBaseTab *TabWidget::channelTab(const QByteArray &id, bool create, bool show) { SLOG_DEBUG("id =" << SimpleID::encode(id) << "create =" << create << "show =" << show); if (!Channel::isCompatibleId(id)) return 0; ChannelBaseTab *tab = 0; if (m_channels.contains(id)) { tab = m_channels.value(id); create = false; } ClientChannel channel = ChatClient::channels()->get(id); if (!channel) { if (!m_prefetch.contains(id)) m_prefetch.append(id); return 0; } if (create) { if (channel->type() == SimpleID::UserId) tab = new PrivateTab(channel, this); else if (channel->type() == SimpleID::ChannelId) tab = new ChannelTab(channel, this); if (tab) { m_channels[id] = tab; tab->setOnline(); addTab(tab, tab->icon(), channel->name()); connect(tab, SIGNAL(actionTriggered(bool)), SLOT(openTab())); if (channel->type() == SimpleID::ChannelId && isAutoPin(channel->id())) tab->pin(); if (m_autoPin.contains(id)) { m_autoPin.removeAll(id); tab->pin(); emit pinned(tab); } } closePage(PROGRESS_TAB); closePage(WELCOME_TAB); } if (show && tab) setCurrentIndex(indexOf(tab)); return tab; }
/*! * Формирование пакета для отправки клиенту заголовка канала. * * \param channel Канал. * \param dest Идентификатор получателя. * \param command Команда. */ ChannelPacket ChannelNotice::channel(ClientChannel channel, const QByteArray &dest, const QString &command) { ChannelPacket packet(new ChannelNotice(channel->id(), dest, command, DateTime::utc())); packet->setDirection(Server2Client); packet->setText(channel->name()); packet->gender = channel->gender().raw(); packet->channelStatus = channel->status().value(); // packet.setData(channel->feeds().headers(0)); if (channel->type() == SimpleID::ChannelId) packet->channels = channel->channels().all(); return packet; }
PrivateTab::PrivateTab(ClientChannel channel, TabWidget *parent) : ChannelBaseTab(channel, LS("talk"), parent) { QVBoxLayout *mainLay = new QVBoxLayout(this); mainLay->addWidget(m_chatView); mainLay->setMargin(0); mainLay->setSpacing(0); setText(channel->name()); ChatClient::channels()->join(id()); connect(ChatClient::channels(), SIGNAL(channel(ChannelInfo)), SLOT(channel(ChannelInfo))); connect(ChatClient::channels(), SIGNAL(quit(QByteArray)), SLOT(quit(QByteArray))); connect(ChatClient::i(), SIGNAL(online()), SLOT(online())); }
bool FixUrlFilter::filter(QList<HtmlToken> &tokens, int options) const { Q_UNUSED(options) QList<HtmlToken> out; QString name; bool remove = false; foreach (const HtmlToken &token, tokens) { if (token.type == HtmlToken::StartTag && token.tag == LS("a")) { HtmlATag tag(token); if (tag.url.startsWith(LS("chat://channel/"))) { ClientChannel user = ChatUrls::channel(QUrl(tag.url)); if (user) name = user->name(); } out.append(token); } else if (!name.isEmpty()) { if (name != token.text) { out.append(HtmlToken(name)); out.append(HtmlToken(HtmlToken::Tag, LS("</a>"))); remove = true; if (token.text.startsWith(name)) out.append(HtmlToken(LC(' ') + token.text.mid(name.size()))); else out.append(LC(' ') + token.text); } else out.append(token); name.clear(); } else if (token.type == HtmlToken::EndTag && token.tag == LS("a") && remove) { remove = false; } else out.append(token); } tokens = out; return true; }
/*! * Преобразует канал в URL адрес. * * \param channel Указатель на канал. * \param action Действие над каналом. */ QUrl ChatUrls::toUrl(ClientChannel channel, const QString &action) { QUrl out(LS("chat://channel")); out.setPath(SimpleID::encode(channel->id()) + (action.isEmpty() ? QString() : "/" + action)); QList<QPair<QString, QString> > queries; queries.append(QPair<QString, QString>(LS("name"), ChatId::toBase32(channel->name().toUtf8()))); queries.append(QPair<QString, QString>(LS("gender"), QString::number(channel->gender().raw()))); # if QT_VERSION >= 0x050000 QUrlQuery query; query.setQueryItems(queries); out.setQuery(query); # else out.setQueryItems(queries); # endif return out; }
bool UrlFilter::filter(QList<HtmlToken> &tokens, int options) const { Q_UNUSED(options) QString name; for (int i = 0; i < tokens.size(); ++i) { const HtmlToken &token = tokens.at(i); if (token.type == HtmlToken::StartTag && token.tag == LS("a")) { HtmlATag tag(tokens.at(i)); if (tag.url.startsWith(LS("chat://channel/"))) { tag.classes = LS("nick"); ClientChannel user = ChatUrls::channel(QUrl(tag.url)); if (user) { tag.classes += LC(' ') + SimpleID::encode(user->id()); name = user->name(); tag.classes += LS(" color-") + Gender::colorToString(user->gender().color()); } tokens[i].text = tag.toText(); } else if (tag.title.isEmpty()) { tag.title = tag.url; tokens[i].text = tag.toText(); } } else if (token.type == HtmlToken::Text && !name.isEmpty()) { tokens[i].text = Qt::escape(name); name.clear(); } } return true; }
#include "feeds/FeedStorage.h" #include "hooks/ClientFeedsImpl.h" #include "net/packets/FeedNotice.h" #include "net/SimpleID.h" #include "sglobal.h" ClientFeedsImpl::ClientFeedsImpl(QObject *parent) : Feeds(parent) { ChatClient::feeds()->hooks()->add(this); } void ClientFeedsImpl::addImpl(ClientChannel channel, const ChannelInfo & /*info*/, const QVariantMap &json) { SCHAT_DEBUG_STREAM("ClientFeedsImpl::addImpl()" << channel->name() << json.keys()) if (json.isEmpty() || !json.contains(FEED_KEY_F)) return; const QVariantMap data = json.value(FEED_KEY_F).toMap(); if (data.isEmpty()) return; QStringList feeds = unsynced(channel, data); feeds.removeAll(FEED_NAME_HOSTS); get(channel->id(), feeds); }
bool PingRequestHandler::processRequest(const YarpString & request, const yarp::os::Bottle & restOfInput, const YarpString & senderChannel, yarp::os::ConnectionWriter * replyMechanism) { #if (! defined(ODL_ENABLE_LOGGING_)) # if MAC_OR_LINUX_ # pragma unused(request,senderChannel) # endif // MAC_OR_LINUX_ #endif // ! defined(ODL_ENABLE_LOGGING_) ODL_OBJENTER(); //#### ODL_S3s("request = ", request, "restOfInput = ", restOfInput.toString(), //#### "senderChannel = ", senderChannel); //#### ODL_P1("replyMechanism = ", replyMechanism); //#### bool result = true; try { // Validate the name as a channel name _response.clear(); if (1 == restOfInput.size()) { yarp::os::Value argument(restOfInput.get(0)); if (argument.isString()) { YarpString argAsString(argument.toString()); if (Endpoint::CheckEndpointName(argAsString)) { RegistryService & theService = static_cast<RegistryService &>(_service); theService.reportStatusChange(argAsString, RegistryService::kRegistryPingFromService); if (theService.checkForExistingService(argAsString)) { // This service is already known, so just update the last-checked time. theService.updateCheckedTimeForChannel(argAsString); } else if (theService.checkForExistingService(argAsString)) { // Second try - something happened with the first call. // This service is already known, so just update the last-checked time. theService.updateCheckedTimeForChannel(argAsString); } else { // Send a 'name' request to the channel YarpString aName = GetRandomChannelName(HIDDEN_CHANNEL_PREFIX_ BUILD_NAME_("ping_", DEFAULT_CHANNEL_ROOT_)); ClientChannel * outChannel = new ClientChannel; if (outChannel) { if (outChannel->openWithRetries(aName, STANDARD_WAIT_TIME_)) { if (outChannel->addOutputWithRetries(argAsString, STANDARD_WAIT_TIME_)) { yarp::os::Bottle message1(MpM_NAME_REQUEST_); yarp::os::Bottle reply; if (outChannel->writeBottle(message1, reply)) { if (theService.processNameResponse(argAsString, ServiceResponse(reply))) { yarp::os::Bottle message2(MpM_LIST_REQUEST_); if (outChannel->writeBottle(message2, reply)) { if (theService.processListResponse(argAsString, ServiceResponse(reply))) { // Remember the response _response.addString(MpM_OK_RESPONSE_); theService.updateCheckedTimeForChannel(argAsString); } else { ODL_LOG("! (theService.processList" //#### "Response(argAsString, reply))"); //#### _response.addString(MpM_FAILED_RESPONSE_); _response.addString("Invalid response to " "'list' request"); } } else { ODL_LOG("! (outChannel->" //#### "writeBottle(message2, reply))"); //#### _response.addString(MpM_FAILED_RESPONSE_); _response.addString("Could not write to channel"); #if defined(MpM_StallOnSendProblem) Stall(); #endif // defined(MpM_StallOnSendProblem) } } else { ODL_LOG("! (theService.processNameResponse(" //#### "argAsString, reply))"); //#### _response.addString(MpM_FAILED_RESPONSE_); _response.addString("Invalid response to 'name' " "request"); } } else { ODL_LOG("! (outChannel->writeBottle(message1, " //#### "reply))"); //#### _response.addString(MpM_FAILED_RESPONSE_); _response.addString("Could not write to channel"); #if defined(MpM_StallOnSendProblem) Stall(); #endif // defined(MpM_StallOnSendProblem) } #if defined(MpM_DoExplicitDisconnect) if (! Utilities::NetworkDisconnectWithRetries(outChannel->name(), argAsString, STANDARD_WAIT_TIME_)) { ODL_LOG("(! Utilities::NetworkDisconnectWith" //#### "Retries(outChannel->name(), " //#### "argAsString, STANDARD_WAIT_TIME_))"); //#### } #endif // defined(MpM_DoExplicitDisconnect) } else { ODL_LOG("! (outChannel->addOutputWithRetries(" //#### "argAsString, STANDARD_WAIT_TIME_))"); //#### _response.addString(MpM_FAILED_RESPONSE_); _response.addString("Could not connect to channel"); _response.addString(argAsString); } #if defined(MpM_DoExplicitClose) outChannel->close(); #endif // defined(MpM_DoExplicitClose) } else { ODL_LOG("! (outChannel->openWithRetries(aName, " //#### "STANDARD_WAIT_TIME_))"); //#### _response.addString(MpM_FAILED_RESPONSE_); _response.addString("Channel could not be opened"); } BaseChannel::RelinquishChannel(outChannel); } else { ODL_LOG("! (outChannel)"); } } } else { ODL_LOG("! (Endpoint::CheckEndpointName(argAsString))"); //#### _response.addString(MpM_FAILED_RESPONSE_); _response.addString("Invalid channel name"); } } else { ODL_LOG("! (argument.isString())"); //#### _response.addString(MpM_FAILED_RESPONSE_); _response.addString("Invalid channel name"); } } else { ODL_LOG("! (1 == restOfInput.size())"); //#### _response.addString(MpM_FAILED_RESPONSE_); _response.addString("Missing channel name or extra arguments to request"); } sendResponse(replyMechanism); } catch (...) { ODL_LOG("Exception caught"); //#### throw; } ODL_OBJEXIT_B(result); //#### return result; } // PingRequestHandler::processRequest