/
NeoChapay
/
telegraf
Обзор
Документация
Войти
/
NeoChapay
/
telegraf
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
src/telegrafutils.cpp
403 строки
18 KB
Nikolay Sinyov
на основе вот этого PR https://github.com/Wunderfitz/harbour-fernschreiber/pull/577/commits/7c0e9e4e5b7485b4cfbab6cf3f250b425802cb1d
12 янв 2025, 00:10
12 янв 2025, 00:10
8634c32
Код
Авторство
О чём код?
#include "telegrafutils.h" #include <QMap> #include <QVariant> #include <QAudioEncoderSettings> #include <QStandardPaths> #include <QDir> #include <QDirIterator> #include <QFile> #include <QUrl> #include <QUrlQuery> #include <QDateTime> #include <QGeoCoordinate> #include <QGeoLocation> #include <QSysInfo> #include <QNetworkRequest> #include <QNetworkReply> #define DEBUG_MODULE TelegrafUtils #include "debuglog.h" namespace { const char _TYPE[] = "@type"; const char TEXT[] = "text"; const char EMOJI[] = "emoji"; const char ANIMATED_EMOJI[] = "animated_emoji"; const char STICKER[] = "sticker"; const char USER_ID[] = "user_id"; const char MESSAGE_SENDER_TYPE_USER[] = "messageSenderUser"; const char MESSAGE_CONTENT_TYPE_TEXT[] = "messageText"; const char MESSAGE_CONTENT_TYPE_STICKER[] = "messageSticker"; const char MESSAGE_CONTENT_TYPE_ANIMATED_EMOJI[] = "messageAnimatedEmoji"; const char MESSAGE_CONTENT_TYPE_PHOTO[] = "messagePhoto"; const char MESSAGE_CONTENT_TYPE_VIDEO[] = "messageVideo"; const char MESSAGE_CONTENT_TYPE_VIDEO_NOTE[] = "messageVideoNote"; const char MESSAGE_CONTENT_TYPE_ANIMATION[] = "messageAnimation"; const char MESSAGE_CONTENT_TYPE_AUDIO[] = "messageAudio"; const char MESSAGE_CONTENT_TYPE_VOICE_NOTE[] = "messageVoiceNote"; const char MESSAGE_CONTENT_TYPE_DOCUMENT[] = "messageDocument"; const char MESSAGE_CONTENT_TYPE_LOCATION[] = "messageLocation"; const char MESSAGE_CONTENT_TYPE_VENUE[] = "messageVenue"; const char MESSAGE_CONTENT_TYPE_CALL[] = "messageCall"; } TelegrafUtils::TelegrafUtils(QObject *parent) : QObject(parent) , manager(new QNetworkAccessManager(this)) { LOG("Initializing audio recorder..."); QString temporaryDirectoryPath = this->getTemporaryDirectoryPath(); QDir temporaryDirectory(temporaryDirectoryPath); if (!temporaryDirectory.exists()) { temporaryDirectory.mkpath(temporaryDirectoryPath); } QAudioEncoderSettings encoderSettings; encoderSettings.setCodec("audio/vorbis"); encoderSettings.setChannelCount(1); encoderSettings.setQuality(QMultimedia::LowQuality); this->audioRecorder.setEncodingSettings(encoderSettings); this->audioRecorder.setContainerFormat("ogg"); QMediaRecorder::Status audioRecorderStatus = this->audioRecorder.status(); this->handleAudioRecorderStatusChanged(audioRecorderStatus); connect(&audioRecorder, SIGNAL(durationChanged(qlonglong)), this, SIGNAL(voiceNoteDurationChanged(qlonglong))); connect(&audioRecorder, SIGNAL(statusChanged(QMediaRecorder::Status)), this, SLOT(handleAudioRecorderStatusChanged(QMediaRecorder::Status))); this->geoPositionInfoSource = QGeoPositionInfoSource::createDefaultSource(this); if (this->geoPositionInfoSource) { LOG("Geolocation successfully initialized..."); this->geoPositionInfoSource->setUpdateInterval(5000); connect(geoPositionInfoSource, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(handleGeoPositionUpdated(QGeoPositionInfo))); } else { LOG("Unable to initialize geolocation!"); } } TelegrafUtils::~TelegrafUtils() { this->cleanUp(); } QString TelegrafUtils::getMessageShortText(TDLibWrapper *tdLibWrapper, const QVariantMap &messageContent, const bool isChannel, const qlonglong currentUserId, const QVariantMap &messageSender) { if (messageContent.isEmpty()) { return QString(); } const QString contentType(messageContent.value(_TYPE).toString()); const QString messageSenderType(messageSender.value(_TYPE).toString()); const qlonglong messageSenderUserId = messageSender.value(USER_ID).toLongLong(); const bool myself = !isChannel && (messageSenderType == MESSAGE_SENDER_TYPE_USER && messageSenderUserId == currentUserId); if (contentType == MESSAGE_CONTENT_TYPE_TEXT) { return messageContent.value(TEXT).toMap().value(TEXT).toString(); } if (contentType == MESSAGE_CONTENT_TYPE_STICKER) { return messageContent.value(STICKER).toMap().value(EMOJI).toString(); } if (contentType == MESSAGE_CONTENT_TYPE_ANIMATED_EMOJI) { return messageContent.value(ANIMATED_EMOJI).toMap().value(STICKER).toMap().value(EMOJI).toString(); } if (contentType == MESSAGE_CONTENT_TYPE_PHOTO) { return myself ? tr("sent a picture", "myself") : tr("sent a picture"); } if (contentType == MESSAGE_CONTENT_TYPE_VIDEO) { return myself ? tr("sent a video", "myself") : tr("sent a video"); } if (contentType == MESSAGE_CONTENT_TYPE_VIDEO_NOTE) { return myself ? tr("sent a video note", "myself") : tr("sent a video note"); } if (contentType == MESSAGE_CONTENT_TYPE_ANIMATION) { return myself ? tr("sent an animation", "myself") : tr("sent an animation"); } if (contentType == MESSAGE_CONTENT_TYPE_AUDIO) { return myself ? tr("sent an audio", "myself") : tr("sent an audio"); } if (contentType == MESSAGE_CONTENT_TYPE_VOICE_NOTE) { return myself ? tr("sent a voice note", "myself") : tr("sent a voice note"); } if (contentType == MESSAGE_CONTENT_TYPE_DOCUMENT) { return myself ? tr("sent a document", "myself") : tr("sent a document"); } if (contentType == MESSAGE_CONTENT_TYPE_LOCATION) { return myself ? tr("sent a location", "myself") : tr("sent a location"); } if (contentType == MESSAGE_CONTENT_TYPE_VENUE) { return myself ? tr("sent a venue", "myself") : tr("sent a venue"); } if (contentType == "messageContactRegistered") { return myself ? tr("have registered with Telegram", "myself") : tr("has registered with Telegram"); } if (contentType == "messageChatJoinByLink") { return myself ? tr("joined this chat", "myself") : tr("joined this chat"); } if (contentType == "messageChatAddMembers") { if (messageSenderType == MESSAGE_SENDER_TYPE_USER && messageSenderUserId == messageContent.value("member_user_ids").toList().at(0).toLongLong()) { return myself ? tr("were added to this chat", "myself") : tr("was added to this chat"); } else { QVariantList memberUserIds = messageContent.value("member_user_ids").toList(); QString addedUserNames; for (int i = 0; i < memberUserIds.size(); i++) { if (i > 0) { addedUserNames += ", "; } addedUserNames += getUserName(tdLibWrapper->getUserInformation(memberUserIds.at(i).toLongLong())); } return myself ? tr("have added %1 to the chat", "myself").arg(addedUserNames) : tr("has added %1 to the chat").arg(addedUserNames); } } if (contentType == "messageChatDeleteMember") { if (messageSenderType == MESSAGE_SENDER_TYPE_USER && messageSenderUserId == messageContent.value("user_id").toLongLong()) { return myself ? tr("left this chat", "myself") : tr("left this chat"); } else { return myself ? tr("have removed %1 from the chat", "myself").arg(getUserName(tdLibWrapper->getUserInformation(messageContent.value("user_id").toLongLong()))) : tr("has removed %1 from the chat").arg(getUserName(tdLibWrapper->getUserInformation(messageContent.value("user_id").toLongLong()))); } } if (contentType == "messageChatChangeTitle") { return myself ? tr("changed the chat title", "myself") : tr("changed the chat title"); } if (contentType == "messagePoll") { if(messageContent.value("poll").toMap().value("type").toMap().value("@type").toString() == "pollTypeQuiz") { return myself ? tr("sent a quiz", "myself") : tr("sent a quiz"); } return myself ? tr("sent a poll", "myself") : tr("sent a poll"); } if (contentType == "messageBasicGroupChatCreate" || contentType == "messageSupergroupChatCreate") { return myself ? tr("created this group", "myself") : tr("created this group"); } if (contentType == "messageChatChangePhoto") { return myself ? tr("changed the chat photo", "myself") : tr("changed the chat photo"); } if (contentType == "messageChatDeletePhoto") { return myself ? tr("deleted the chat photo", "myself") : tr("deleted the chat photo"); } if (contentType == "messageChatSetTtl") { return myself ? tr("changed the secret chat TTL setting", "myself") : tr("changed the secret chat TTL setting"); } if (contentType == "messageChatUpgradeFrom" || contentType == "messageChatUpgradeTo") { return myself ? tr("upgraded this group to a supergroup", "myself") : tr("upgraded this group to a supergroup"); } if (contentType == "messageCustomServiceAction") { return messageContent.value(TEXT).toString(); } if (contentType == "messagePinMessage") { return myself ? tr("changed the pinned message", "myself") : tr("changed the pinned message"); } if (contentType == "messageExpiredPhoto") { return myself ? tr("sent a self-destructing photo that is expired", "myself") : tr("sent a self-destructing photo that is expired"); } if (contentType == "messageExpiredVideo") { return myself ? tr("sent a self-destructing video that is expired", "myself") : tr("sent a self-destructing video that is expired"); } if (contentType == "messageScreenshotTaken") { return myself ? tr("created a screenshot in this chat", "myself") : tr("created a screenshot in this chat"); } if (contentType == "messageGameScore") { qint32 score = messageContent.value("score").toInt(); return myself ? tr("scored %Ln points", "myself", score) : tr("scored %Ln points", "", score); } if (contentType == "messageGame") { return myself ? tr("sent a game", "myself") : tr("sent a game"); } if (contentType == MESSAGE_CONTENT_TYPE_CALL) { bool video = messageContent.value("is_video").toBool(); const QString discardReason(messageContent.value("discard_reason").toMap().value(_TYPE).toString()); uint duration = messageContent.value("duration").toUInt(); uint minutes = floor(duration / 60); uint seconds = duration % 60; QString durationString = minutes > 0 ? tr("%1 min %2 sec").arg(minutes).arg(seconds) : tr("%1 sec").arg(seconds); if (video) { if (discardReason == "callDiscardReasonMissed") return tr("missed video call"); else if (discardReason == "callDiscardReasonDeclined") return tr("declined video call"); else if (discardReason == "callDiscardReasonDisconnected") return tr("interrupted video call: %1").arg(durationString); else if (discardReason == "callDiscardReasonHungUp" || discardReason == "callDiscardReasonEmpty") return myself ? tr("outgoing video call: %1", "myself").arg(durationString) : tr("incoming video call: %1").arg(durationString); } else { if (discardReason == "callDiscardReasonMissed") return tr("missed call"); else if (discardReason == "callDiscardReasonDeclined") return tr("declined call"); else if (discardReason == "callDiscardReasonDisconnected") return tr("interrupted call: %1").arg(durationString); else if (discardReason == "callDiscardReasonHungUp" ||discardReason == "callDiscardReasonEmpty") return myself ? tr("outgoing call: %1", "myself").arg(durationString) : tr("incoming call: %1").arg(durationString); } } if (contentType == "messageUnsupported") { return myself ? tr("sent an unsupported message", "myself") : tr("sent an unsupported message"); } return myself ? tr("sent an unsupported message: %1", "myself").arg(contentType.mid(7)) : tr("sent an unsupported message: %1").arg(contentType.mid(7)); } QString TelegrafUtils::getUserName(const QVariantMap &userInformation) { const QString firstName = userInformation.value("first_name").toString(); const QString lastName = userInformation.value("last_name").toString(); return QString(firstName + " " + lastName).trimmed(); } void TelegrafUtils::startRecordingVoiceNote() { LOG("Start recording voice note..."); QDateTime thisIsNow = QDateTime::currentDateTime(); this->audioRecorder.setOutputLocation(QUrl::fromLocalFile(this->getTemporaryDirectoryPath() + "/voicenote-" + thisIsNow.toString("yyyy-MM-dd-HH-mm-ss") + ".ogg")); this->audioRecorder.setVolume(1); this->audioRecorder.record(); } void TelegrafUtils::stopRecordingVoiceNote() { LOG("Stop recording voice note..."); this->audioRecorder.stop(); } QString TelegrafUtils::voiceNotePath() { return this->audioRecorder.outputLocation().toLocalFile(); } TelegrafUtils::VoiceNoteRecordingState TelegrafUtils::getVoiceNoteRecordingState() { return this->voiceNoteRecordingState; } void TelegrafUtils::startGeoLocationUpdates() { if (this->geoPositionInfoSource) { this->geoPositionInfoSource->startUpdates(); } } void TelegrafUtils::stopGeoLocationUpdates() { if (this->geoPositionInfoSource) { this->geoPositionInfoSource->stopUpdates(); } } bool TelegrafUtils::supportsGeoLocation() { return this->geoPositionInfoSource; } QString TelegrafUtils::getOSVersion() { return QSysInfo::productVersion(); } void TelegrafUtils::initiateReverseGeocode(double latitude, double longitude) { LOG("Initiating reverse geocode:" << latitude << longitude); QUrl url = QUrl("https://nominatim.openstreetmap.org/reverse"); QUrlQuery urlQuery; urlQuery.addQueryItem("lat", QString::number(latitude)); urlQuery.addQueryItem("lon", QString::number(longitude)); urlQuery.addQueryItem("format", "json"); url.setQuery(urlQuery); QNetworkRequest request(url); request.setHeader(QNetworkRequest::UserAgentHeader, "Telegraf (Aurora OS)"); request.setRawHeader(QByteArray("Accept"), QByteArray("application/json")); request.setRawHeader(QByteArray("Accept-Charset"), QByteArray("utf-8")); request.setRawHeader(QByteArray("Connection"), QByteArray("close")); request.setRawHeader(QByteArray("Cache-Control"), QByteArray("max-age=0")); QNetworkReply *reply = manager->get(request); connect(reply, SIGNAL(finished()), this, SLOT(handleReverseGeocodeFinished())); } void TelegrafUtils::handleAudioRecorderStatusChanged(QMediaRecorder::Status status) { LOG("Audio recorder status changed:" << status); switch (status) { case QMediaRecorder::UnavailableStatus: case QMediaRecorder::UnloadedStatus: case QMediaRecorder::LoadingStatus: this->voiceNoteRecordingState = VoiceNoteRecordingState::Unavailable; break; case QMediaRecorder::LoadedStatus: case QMediaRecorder::PausedStatus: this->voiceNoteRecordingState = VoiceNoteRecordingState::Ready; break; case QMediaRecorder::StartingStatus: this->voiceNoteRecordingState = VoiceNoteRecordingState::Starting; break; case QMediaRecorder::FinalizingStatus: this->voiceNoteRecordingState = VoiceNoteRecordingState::Stopping; break; case QMediaRecorder::RecordingStatus: this->voiceNoteRecordingState = VoiceNoteRecordingState::Recording; break; } emit voiceNoteRecordingStateChanged(this->voiceNoteRecordingState); } void TelegrafUtils::handleGeoPositionUpdated(const QGeoPositionInfo &info) { LOG("Geo position was updated"); QVariantMap positionInformation; if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) { positionInformation.insert("horizontalAccuracy", info.attribute(QGeoPositionInfo::HorizontalAccuracy)); } else { positionInformation.insert("horizontalAccuracy", 0); } if (info.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) { positionInformation.insert("verticalAccuracy", info.attribute(QGeoPositionInfo::VerticalAccuracy)); } else { positionInformation.insert("verticalAccuracy", 0); } QGeoCoordinate geoCoordinate = info.coordinate(); positionInformation.insert("latitude", geoCoordinate.latitude()); positionInformation.insert("longitude", geoCoordinate.longitude()); this->initiateReverseGeocode(geoCoordinate.latitude(), geoCoordinate.longitude()); emit newPositionInformation(positionInformation); } void TelegrafUtils::handleReverseGeocodeFinished() { qDebug() << "TelegrafUtils::handleReverseGeocodeFinished"; QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); reply->deleteLater(); if (reply->error() != QNetworkReply::NoError) { return; } QJsonDocument jsonDocument = QJsonDocument::fromJson(reply->readAll()); qDebug().noquote() << jsonDocument.toJson(QJsonDocument::Indented); if (jsonDocument.isObject()) { QJsonObject responseObject = jsonDocument.object(); emit newGeocodedAddress(responseObject.value("display_name").toString()); } } void TelegrafUtils::cleanUp() { if (this->geoPositionInfoSource) { this->geoPositionInfoSource->stopUpdates(); } QString temporaryDirectoryPath = this->getTemporaryDirectoryPath(); QDirIterator temporaryDirectoryIterator(temporaryDirectoryPath, QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks, QDirIterator::Subdirectories); while (temporaryDirectoryIterator.hasNext()) { QString nextFilePath = temporaryDirectoryIterator.next(); if (QFile::remove(nextFilePath)) { LOG("Temporary file removed " << nextFilePath); } else { LOG("Error removing temporary file " << nextFilePath); } } } QString TelegrafUtils::getTemporaryDirectoryPath() { return QStandardPaths::writableLocation(QStandardPaths::TempLocation) + + "/ru.telegrafaurora.telegraf"; }