button icons and dynamic news tabs

This commit is contained in:
LubuWest 2024-04-05 19:28:47 +02:00
commit 8391b028f4
333 changed files with 2193 additions and 2040 deletions

59
src/common/alarm.h Normal file
View file

@ -0,0 +1,59 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef ALARM_H
#define ALARM_H
#include <QObject>
class ALARM : public QObject
{
Q_OBJECT
//Q_PROPERTY(int alarmtime READ alarmtime WRITE setAlarm NOTIFY alarmChanged)
public:
static ALARM *instance();
explicit ALARM(QObject *parent = 0);
//int alarmtime() const;
signals:
void alarmChanged(QString url);
public slots:
void setAlarm(int time);
void notify(QString title, QString text, int id);
private:
int m_time;
};
#endif // UPDATENEWS_H

View file

@ -0,0 +1,64 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "alarm.h"
#include <QtCore/QDebug>
#include "AndroidNative/systemdispatcher.h"
ALARM *ALARM::instance()
{
static ALARM alarm;
return &alarm;
}
ALARM::ALARM(QObject *parent) : QObject(parent){}
void ALARM::setAlarm(int interval)
{
//qDebug() << "alarm "<< interval;
QVariantMap message;
message["value"] = interval;
AndroidNative::SystemDispatcher::instance()->loadClass("androidnative.Util");
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setPostNotification", message);
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setSchedule", message);
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.stopService", message);
}
void ALARM::notify(QString title, QString text, int id)
{
//qDebug() << "notify "<< title << text;
QVariantMap message;
message["title"] = title;
message["message"] = text;
message["id"] = id;
AndroidNative::SystemDispatcher::instance()->loadClass("androidnative.Util");
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setNotification", message);
}

80
src/common/alarmlinux.cpp Normal file
View file

@ -0,0 +1,80 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "alarm.h"
#include <QtCore/QDebug>
#include <QtDBus/QtDBus>
#include <QJsonArray>
#include <QStringList>
ALARM *ALARM::instance()
{
static ALARM alarm;
return &alarm;
}
ALARM::ALARM(QObject *parent) : QObject(parent){}
void ALARM::setAlarm(int interval)
{
//QVariantMap message;
//message["value"] = interval;
if (interval==0){
QProcess processDisable;
int intDisable = processDisable.execute("systemctl", QStringList() <<"--user"<<"disable"<<"--now"<<"friendiqa-sync.timer");
qDebug() << " intEnable "<<intDisable;
}else{
QProcess processReload;
int intReload = processReload.execute("systemctl", QStringList()<<"--user"<<"daemon-reload");
QProcess processEnable;
int intEnable = processEnable.execute("systemctl", QStringList() <<"--user"<<"enable"<<"--now"<<"friendiqa-sync.timer");
qDebug() << "intReload "<<intReload << " intEnable "<<intEnable;
}
}
void ALARM::notify(QString title, QString text, int id)
{
//qDebug() << title << text;
// QVariantMap message;
// message["title"] = title;
// message["message"] = text;
QStringList actionlist;
QMap<QString,QVariant> hint;
QDBusConnection bus = QDBusConnection::sessionBus();
QDBusInterface dbus_iface("org.freedesktop.Notifications", "/org/freedesktop/Notifications",
"org.freedesktop.Notifications", bus);
QString appname="Friendiqa";
uint v=12321;
if (dbus_iface.isValid()){
dbus_iface.call("Notify",appname,v,"",title,text,actionlist,hint,10000);
//qDebug() << "Qdebug error " << dbus_iface.lastError();
}
}

View file

@ -0,0 +1,262 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QQuickTextDocument>
#include <QTextCharFormat>
#include <QStringDecoder>
#include <QTextDocument>
#include <QTextDocumentFragment>
#include <QTextList>
#include <QDebug>
#include "documenthandler.h"
DocumentHandler::DocumentHandler(QObject *parent)
: QObject(parent)
, m_document(nullptr)
, m_cursorPosition(-1)
, m_selectionStart(0)
, m_selectionEnd(0)
{
}
QQuickTextDocument *DocumentHandler::document() const
{
return m_document;
}
void DocumentHandler::setDocument(QQuickTextDocument *document)
{
if (document == m_document)
return;
if (m_document)
disconnect(m_document->textDocument(), &QTextDocument::modificationChanged, this, &DocumentHandler::modifiedChanged);
m_document = document;
if (m_document)
connect(m_document->textDocument(), &QTextDocument::modificationChanged, this, &DocumentHandler::modifiedChanged);
emit documentChanged();
}
int DocumentHandler::cursorPosition() const
{
return m_cursorPosition;
}
void DocumentHandler::setCursorPosition(int position)
{
if (position == m_cursorPosition)
return;
m_cursorPosition = position;
emit cursorPositionChanged();
}
int DocumentHandler::selectionStart() const
{
return m_selectionStart;
}
void DocumentHandler::setSelectionStart(int position)
{
if (position == m_selectionStart)
return;
m_selectionStart = position;
emit selectionStartChanged();
}
int DocumentHandler::selectionEnd() const
{
return m_selectionEnd;
}
void DocumentHandler::setSelectionEnd(int position)
{
if (position == m_selectionEnd)
return;
m_selectionEnd = position;
emit selectionEndChanged();
}
QTextCursor DocumentHandler::textCursor() const
{
QTextDocument *doc = textDocument();
if (!doc)
return QTextCursor();
QTextCursor cursor = QTextCursor(doc);
if (m_selectionStart != m_selectionEnd) {
cursor.setPosition(m_selectionStart);
cursor.setPosition(m_selectionEnd, QTextCursor::KeepAnchor);
} else {
cursor.setPosition(m_cursorPosition);
}
return cursor;
}
QTextDocument *DocumentHandler::textDocument() const
{
if (!m_document)
return nullptr;
return m_document->textDocument();
}
void DocumentHandler::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
{
QTextCursor cursor = textCursor();
if (!cursor.hasSelection())
cursor.select(QTextCursor::WordUnderCursor);
cursor.mergeCharFormat(format);
}
bool DocumentHandler::modified() const
{
return m_document && m_document->textDocument()->isModified();
}
void DocumentHandler::setModified(bool m)
{
if (m_document)
m_document->textDocument()->setModified(m);
}
QFont DocumentHandler::font() const
{
QTextCursor cursor = textCursor();
if (cursor.isNull())
return m_document->textDocument()->defaultFont();
QTextCharFormat format = cursor.charFormat();
return format.font();
}
void DocumentHandler::setFont(const QFont & font){
QTextCursor cursor = textCursor();
if (!cursor.isNull() && cursor.charFormat().font() == font)
return;
QTextCharFormat format;
format.setFont(font);
mergeFormatOnWordOrSelection(format);
emit fontChanged();
}
bool DocumentHandler::bold() const
{
const QTextCursor cursor = textCursor();
if (cursor.isNull())
return m_document->textDocument()->defaultFont().bold();
return cursor.charFormat().font().bold();
}
void DocumentHandler::setBold(bool bold)
{
const QTextCursor cursor = textCursor();
if (!cursor.isNull() && cursor.charFormat().font().bold() == bold)
return;
QFont font = cursor.charFormat().font();
font.setBold(bold);
QTextCharFormat format;
format.setFont(font);
mergeFormatOnWordOrSelection(format);
emit boldChanged();
}
bool DocumentHandler::italic() const
{
const QTextCursor cursor = textCursor();
if (cursor.isNull())
return m_document->textDocument()->defaultFont().italic();
return cursor.charFormat().font().italic();
}
void DocumentHandler::setItalic(bool italic)
{
const QTextCursor cursor = textCursor();
if (!cursor.isNull() && cursor.charFormat().font().italic() == italic)
return;
QFont font = cursor.charFormat().font();
font.setItalic(italic);
QTextCharFormat format;
format.setFont(font);
mergeFormatOnWordOrSelection(format);
emit italicChanged();
}
bool DocumentHandler::liststyle() const
{
const QTextCursor cursor = textCursor();
if (cursor.isNull())
return false;
return bool(cursor.currentList());
}
void DocumentHandler::setListstyle(bool liststyle)
{
QTextCursor cursor = textCursor();
if (!cursor.isNull() && !liststyle){
cursor.currentList()->remove(cursor.block());
emit liststyleChanged();
}else{
cursor.createList(QTextListFormat::ListDisc);
emit liststyleChanged();
}
}
bool DocumentHandler::codeblock() const
{
const QTextCursor cursor = textCursor();
if (cursor.isNull())
return false;
qDebug()<< QTextDocumentFragment(cursor).toPlainText();
return bool(QTextDocumentFragment(cursor).toMarkdown().contains("```"));
}
void DocumentHandler::setCodeblock(bool codeblock)
{
QTextCursor cursor = textCursor();
if (!cursor.isNull() && !codeblock){
qDebug()<< "!codeblock ```\n" + QTextDocumentFragment(cursor).toMarkdown() + "\n```";
cursor.insertMarkdown("```\n" + QTextDocumentFragment(cursor).toMarkdown() + "\n```");
emit codeblockChanged();
}
else{
qDebug()<< "```\n" + QTextDocumentFragment(cursor).toMarkdown() + "\n```";
cursor.insertMarkdown(QTextDocumentFragment(cursor).toMarkdown().remove("```"));
emit codeblockChanged();
}
}

View file

@ -0,0 +1,114 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef DOCUMENTHANDLER_H
#define DOCUMENTHANDLER_H
//#include <QFont>
#include <QObject>
#include <QTextCursor>
#include <QTextDocument>
#include <QQuickTextDocument>
//QT_BEGIN_NAMESPACE
//class QTextDocument;
//class QQuickTextDocument;
//QT_END_NAMESPACE
class DocumentHandler : public QObject{
Q_OBJECT
Q_PROPERTY(QQuickTextDocument *document READ document WRITE setDocument NOTIFY documentChanged)
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged)
Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged)
Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
Q_PROPERTY(bool bold READ bold WRITE setBold NOTIFY boldChanged)
Q_PROPERTY(bool italic READ italic WRITE setItalic NOTIFY italicChanged)
Q_PROPERTY(bool liststyle READ liststyle WRITE setListstyle NOTIFY liststyleChanged)
Q_PROPERTY(bool codeblock READ codeblock WRITE setCodeblock NOTIFY codeblockChanged)
Q_PROPERTY(bool modified READ modified WRITE setModified NOTIFY modifiedChanged)
public:
explicit DocumentHandler(QObject *parent = nullptr);
QQuickTextDocument *document() const;
void setDocument(QQuickTextDocument *document);
int cursorPosition() const;
void setCursorPosition(int position);
int selectionStart() const;
void setSelectionStart(int position);
int selectionEnd() const;
void setSelectionEnd(int position);
QFont font() const;
void setFont(const QFont & font);
bool bold() const;
void setBold(bool bold);
bool italic() const;
void setItalic(bool italic);
bool liststyle() const;
void setListstyle(bool liststyle);
bool modified() const;
void setModified(bool m);
bool codeblock() const;
void setCodeblock(bool codeblock);
signals:
void documentChanged();
void cursorPositionChanged();
void selectionStartChanged();
void selectionEndChanged();
void fontChanged();
void boldChanged();
void italicChanged();
void liststyleChanged();
void codeblockChanged();
void error(const QString &message);
void modifiedChanged();
private:
QTextCursor textCursor() const;
QTextDocument *textDocument() const;
void mergeFormatOnWordOrSelection(const QTextCharFormat &format);
QQuickTextDocument *m_document;
int m_cursorPosition;
int m_selectionStart;
int m_selectionEnd;
};
#endif // DOCUMENTHANDLER_H

192
src/common/filesystem.cpp Normal file
View file

@ -0,0 +1,192 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "filesystem.h"
#include <QDebug>
FILESYSTEM *FILESYSTEM::instance()
{
static FILESYSTEM filesystem;
return &filesystem;
}
FILESYSTEM::FILESYSTEM(QObject *parent) : QObject(parent){}
void FILESYSTEM::setDirectory(QString Directory)
{
if (Directory!=m_Directory) {
m_Directory = Directory;
emit directoryChanged();
}
}
QString FILESYSTEM::Directory() const
{
return m_Directory;
}
void FILESYSTEM::setVisibility(bool Visibility)
{
if (Visibility!=m_Visibility) {
m_Visibility = Visibility;
emit visibilityChanged();
}
}
bool FILESYSTEM::Visibility()
{
return m_Visibility;
}
QString FILESYSTEM::homePath() const
{
QString homeDir=QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);;
return homeDir;
}
//QString FILESYSTEM::cameraPath() const
//{
//QAndroidJniObject object = QAndroidJniObject::getStaticObjectField<jstring>("android.os.Environment", "DIRECTORY_DCIM");
//QAndroidJniObject dcim =QAndroidJniObject::callStaticObjectMethod("android.os.Environment","getExternalStoragePublicDirectory", "(Ljava/lang/String;)Ljava/io/File;", object.object<jobject>());
// return dcim.toString();
//}
//bool FILESYSTEM::direxist(QString Directory) const
//{QDir dir(Directory);
// return dir.exists();
//}
bool FILESYSTEM::fileexist(QString name)
{ return QFile::exists(name);
}
void FILESYSTEM::makeDir(QString name)
{
QDir dir(m_Directory);
if (dir.mkdir(name)){
emit success(name);
}
else {
emit error(name,1);
}
}
void FILESYSTEM::makePath(QString name)
{
QDir dir(m_Directory);
if (dir.mkpath(name)){
emit success(name);
}
else {
qDebug() << "makepath error" <<name;
emit error(name,1);}
}
void FILESYSTEM::rmDir()
{
QDir dir(m_Directory);
if (dir.removeRecursively()){
emit success(m_Directory);
}
else {emit error(m_Directory,1);}
}
void FILESYSTEM::rmFile(QString name)
{
QDir dir(m_Directory);
if(dir.remove(name)){
emit success(name);
}
else {emit error(name,1);}
}
QFileInfoList FILESYSTEM::fileList()
{
QDir dir(m_Directory);
QStringList filters;
filters << "*.png" <<"*.PNG" << "*.jpg" << "*.JPG" << "*.JPEG";
dir.setNameFilters(filters);
dir.setSorting(QDir::Time | QDir::Reversed);
return dir.entryInfoList();
}
bool FILESYSTEM::isAutostart() {
QFileInfo check_file(QDir::homePath() + "/.config/autostart/friendiqa.desktop");
if (check_file.exists() && check_file.isFile()) {
return true;
}
return false;
}
void FILESYSTEM::setAutostart(bool autostart) {
QString path = QDir::homePath() + "/.config/autostart/";
QString name ="friendiqa.desktop";
QFile file(path+name);
file.remove();
if(autostart) {
QDir dir(path);
if(!dir.exists()) {
dir.mkpath(path);
}
if (file.open(QIODevice::ReadWrite)) {
QTextStream stream(&file);
stream << "[Desktop Entry]" << Qt::endl;
stream << "Name=Friendiqa" << Qt::endl;
stream << "Exec=friendiqa -background %u" << Qt::endl;
stream << "Terminal=false" << Qt::endl;
stream << "Icon=Friendiqa.svg" << Qt::endl;
stream << "Type=Application" << Qt::endl;
stream << "StartupNotify=false" << Qt::endl;
stream << "X-GNOME-Autostart-enabled=true" << Qt::endl;
}
}
}
QString FILESYSTEM::osType() const
{
QString m_osType;
if(QSysInfo::productType()==QString("android")){
m_osType="Android";
}else{
m_osType="Linux";
}
return m_osType;
}
QString FILESYSTEM::hostname() const
{
return QSysInfo::machineHostName();
}

97
src/common/filesystem.h Normal file
View file

@ -0,0 +1,97 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#include <QDir>
#include <QObject>
#include <QStandardPaths>
#include <QSysInfo>
//#include <QtAndroidExtras>
//#include <QAndroidActivityResultReceiver>
class FILESYSTEM : public QObject//, public QAndroidActivityResultReceiver
{
Q_OBJECT
Q_PROPERTY(QString Directory READ Directory WRITE setDirectory NOTIFY directoryChanged)
Q_PROPERTY(bool Visibility READ Visibility WRITE setVisibility NOTIFY visibilityChanged)
//Q_PROPERTY(bool direxist READ direxist)
Q_PROPERTY(QString homePath READ homePath)
Q_PROPERTY(bool isAutostart READ isAutostart NOTIFY isAutostartChanged)
Q_PROPERTY(QString osType READ osType CONSTANT)
Q_PROPERTY(QString hostname READ hostname CONSTANT)
//Q_PROPERTY(QString cameraPath READ cameraPath)
public:
static FILESYSTEM *instance();
explicit FILESYSTEM(QObject *parent = 0);
void setDirectory(QString Directory);
void setVisibility(bool Visibility);
QString Directory() const;
QFileInfoList fileList();
//bool direxist(QString Directory);
QString homePath() const;
bool Visibility();
bool isAutostart();
QString osType() const;
QString hostname() const;
//QString cameraPath() const;
// virtual void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data);
signals:
//void imageselected(QString);
void directoryChanged();
void visibilityChanged();
void isAutostartChanged();
//void fileListContent(QList data);
void success(QString data);
void error(QString data, int code);
public slots:
bool fileexist(QString name);
void makeDir(QString name);
void makePath(QString name);
void rmDir();
void rmFile(QString name);
void setAutostart(bool autostart);
//void searchImage();
//void fileList();
private:
QString m_Directory;
QString homeDir;
bool m_Visibility;
//QList m_Filelist;
};
#endif // FILSYSTEM_H

View file

@ -0,0 +1,170 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "filesystem.h"
#include <QtAndroidExtras>
FILESYSTEM *FILESYSTEM::instance()
{
static FILESYSTEM filesystem;
return &filesystem;
}
FILESYSTEM::FILESYSTEM(QObject *parent) : QObject(parent){}
void FILESYSTEM::setDirectory(QString Directory)
{
if (Directory!=m_Directory) {
m_Directory = Directory;
emit directoryChanged();
}
}
QString FILESYSTEM::Directory() const
{
return m_Directory;
}
void FILESYSTEM::setVisibility(bool Visibility)
{
if (Visibility!=m_Visibility) {
m_Visibility = Visibility;
emit visibilityChanged();
}
}
bool FILESYSTEM::Visibility()
{
return m_Visibility;
}
QString FILESYSTEM::homePath() const
{
QAndroidJniObject activity =QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative","activity", "()Landroid/app/Activity;");
QAndroidJniObject dir = activity.callObjectMethod("getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;", NULL);
QString homeDir=dir.toString();
return homeDir;
}
bool FILESYSTEM::fileexist(QString name)
{ return QFile::exists(name);
}
void FILESYSTEM::makeDir(QString name)
{
QDir dir(m_Directory);
if (dir.mkdir(name)){
emit success(name);
}
else {
emit error(name,1);
}
}
void FILESYSTEM::makePath(QString name)
{
QDir dir(m_Directory);
if (dir.mkpath(name)){
emit success(name);
}
else {
emit error(name,1);}
}
void FILESYSTEM::rmDir()
{
QDir dir(m_Directory);
if (dir.removeRecursively()){
emit success(m_Directory);
}
else {emit error(m_Directory,1);}
}
void FILESYSTEM::rmFile(QString name)
{
QDir dir(m_Directory);
if(dir.remove(name)){
emit success(name);
}
else {emit error(name,1);}
}
QFileInfoList FILESYSTEM::fileList()
{
QDir dir(m_Directory);
QStringList filters;
filters << "*.png" <<"*.PNG" << "*.jpg" << "*.JPG" << "*.JPEG";
dir.setNameFilters(filters);
dir.setSorting(QDir::Time | QDir::Reversed);
return dir.entryInfoList();
}
bool FILESYSTEM::isAutostart() {
QFileInfo check_file(QDir::homePath() + "/.config/autostart/friendiqa.desktop");
if (check_file.exists() && check_file.isFile()) {
qDebug()<<"autostart "<<true;
return true;
}
qDebug()<<"autostart "<<false;
return false;
}
void FILESYSTEM::setAutostart(bool autostart) {
QString path = QDir::homePath() + "/.config/autostart/";
QString name ="friendiqa.desktop";
QFile file(path+name);
file.remove();
if(autostart) {
QDir dir(path);
if(!dir.exists()) {
dir.mkpath(path);
}
if (file.open(QIODevice::ReadWrite)) {
QTextStream stream(&file);
stream << "[Desktop Entry]" << Qt::endl;
stream << "Exec=friendiqa -background %u" << Qt::endl;
stream << "Type=Application" << Qt::endl;
}
}
}
QString FILESYSTEM::osType() const
{
return QSysInfo::productType();
}
QString FILESYSTEM::hostname() const
{
return QSysInfo::machineHostName();
}

131
src/common/friendiqa.cpp Normal file
View file

@ -0,0 +1,131 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QApplication>
#include <QtQml/QQmlEngine>
#include <QtQml/qqml.h>
//#include <QtWebEngine>
//#include <QAndroidService>
//#include <QtAndroid>
#include <QtQuick>
#include "xhr.h"
#include "updatenews.h"
#include "filesystem.h"
//#include "remoteauthasyncimageprovider.h"
#include "alarm.h"
#include "oauth.h"
#include "documenthandler.h"
//#include "AndroidNative/systemdispatcher.h"
//#include "AndroidNative/environment.h"
//#include "AndroidNative/debug.h"
//#include "AndroidNative/mediascannerconnection.h"
//#include <QQuickWidget>
#include <QSystemTrayIcon>
#include <QQmlContext>
#include <QQuickStyle>
// Declare a user-defined data type to work with an icon in QML
Q_DECLARE_METATYPE(QSystemTrayIcon::ActivationReason)
#ifdef Q_OS_ANDROID
#include <QtAndroidExtras/QAndroidJniObject>
#include <QtAndroidExtras/QAndroidJniEnvironment>
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
Q_UNUSED(vm);
qDebug("NativeInterface::JNI_OnLoad()"); // It must call this function within JNI_OnLoad to enable System Dispatcher
AndroidNative::SystemDispatcher::registerNatives();
return JNI_VERSION_1_6;
}
#endif
int main(int argc, char *argv[]) {
//qDebug()<< "argv Friendiqa"<< (qstrcmp(argv[1],"-service")==0) <<" argv2" <<argv[1];
QCoreApplication::setApplicationName("Friendiqa");
QCoreApplication::setOrganizationName("Friendiqa");
QApplication app(argc, argv);
if (qstrcmp(argv[1],"-service")==0){
//qDebug()<<"FriendiqaMain Service";
//QAndroidService app(argc, argv);
UPDATENEWS* updatenews= UPDATENEWS::instance();
updatenews->setDatabase();
updatenews->login();
updatenews->setSyncAll(true);
updatenews->startsync();
app.connect (updatenews,SIGNAL(quitapp()),&app,SLOT(quit()));
//QtAndroid::androidService().callMethod<void>("stopSelf");
return app.exec();
}
else{
QQmlApplicationEngine view;
//view.setResizeMode(QQuickView::SizeRootObjectToView);
app.setWindowIcon(QIcon(":/assets/Friendiqa.ico"));
QTranslator qtTranslator;
if(qtTranslator.load("friendiqa-" + QLocale::system().name(),":/translations"))
{app.installTranslator(&qtTranslator);}
// RemoteAuthAsyncImageProvider *imageProvider = new RemoteAuthAsyncImageProvider;
// view.addImageProvider("remoteauthimage",imageProvider);
// view.rootContext()->setContextProperty("remoteauth", imageProvider);
XHR* xhr = XHR::instance();
view.rootContext()->setContextProperty("xhr", xhr);
FILESYSTEM* filesystem = FILESYSTEM::instance();
if (qstrcmp(argv[1],"-background")==0){
filesystem->setVisibility(false);
} else{filesystem->setVisibility(true);}
view.rootContext()->setContextProperty("filesystem", filesystem);
ALARM* alarm = ALARM::instance();
view.rootContext()->setContextProperty("alarm", alarm);
UPDATENEWS* updatenews = UPDATENEWS::instance();
view.rootContext()->setContextProperty("updatenews", updatenews);
updatenews->setDatabase();
OAuthWrapper* oauth2 = OAuthWrapper::instance();
view.rootContext()->setContextProperty("oauth2", oauth2);
qmlRegisterType<DocumentHandler>("io.qt.examples.texteditor", 1, 0, "DocumentHandler");
qmlRegisterType<QSystemTrayIcon>("QSystemTrayIcon", 1, 0, "QSystemTrayIcon");
qRegisterMetaType<QSystemTrayIcon::ActivationReason>("ActivationReason");
view.rootContext()->setContextProperty("iconTrayBlack", QIcon(QPixmap(":/assets/friendica-tray-black.svg")));
view.rootContext()->setContextProperty("iconTrayWhite", QIcon(QPixmap(":/assets/friendica-tray-white.svg")));
view.rootContext()->setContextProperty("iconTrayAvailable", QSystemTrayIcon::isSystemTrayAvailable());
if(updatenews->getStyle() != 0){
QQuickStyle::setStyle("Material");
}
view.load(QUrl("qrc:/qml/friendiqa.qml"));
view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));
return app.exec();
}
}

88
src/common/oauth.cpp Normal file
View file

@ -0,0 +1,88 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2023 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "oauth.h"
#include <QtGui>
#include <QtCore>
#include <QtNetworkAuth>
OAuthWrapper *OAuthWrapper::instance()
{
static OAuthWrapper oa2;
return &oa2;
}
OAuthWrapper::OAuthWrapper(QObject *parent) : QObject(parent)
{
auto replyHandler = new QOAuthHttpServerReplyHandler(1337, this);
oauth2.setReplyHandler(replyHandler);
oauth2.setScope("read+write+follow+push");
connect(&oauth2, &QOAuth2AuthorizationCodeFlow::statusChanged, [=](
QAbstractOAuth::Status status) {
if (status == QAbstractOAuth::Status::Granted){
QMapIterator<QString, QVariant> i(oauth2.extraTokens());
while (i.hasNext()) {
i.next();
//qDebug() << i.key() << ": " << i.value() << Qt::endl;
}
emit success(oauth2.token());
}
});
connect(&oauth2, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser,
&QDesktopServices::openUrl);
}
void OAuthWrapper::setClientId(QString clientid)
{
m_clientid = clientid;
}
void OAuthWrapper::setServer(QString server)
{
m_server = server;
}
void OAuthWrapper::setClientSecret(QString clientsecret)
{
m_clientsecret = clientsecret;
}
void OAuthWrapper::grant()
{
oauth2.setClientIdentifier(m_clientid);
oauth2.setAuthorizationUrl(QUrl(m_server + "/oauth/authorize"));
oauth2.setAccessTokenUrl(QUrl(m_server + "/oauth/token"));
oauth2.setClientIdentifierSharedKey(m_clientsecret);
oauth2.grant();
}

71
src/common/oauth.h Normal file
View file

@ -0,0 +1,71 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef OAUTH_H
#define OAUTH_H
#include <QtCore>
#include <QtNetwork>
#include <QOAuth2AuthorizationCodeFlow>
class OAuthWrapper : public QObject//, public QAndroidActivityResultReceiver
{
Q_OBJECT
public:
OAuthWrapper(QObject *parent = nullptr);;
OAuthWrapper(const QString &clientIdentifier, QObject *parent = nullptr);
static OAuthWrapper *instance();
// bool isPermanent() const;
// void setPermanent(bool value);
signals:
void success(QString token);
void error(QString error);
public slots:
void grant();
void setServer(QString server);
void setClientId(QString clientid);
void setClientSecret(QString clientsecret);
private:
QOAuth2AuthorizationCodeFlow oauth2;
// bool permanent = false;
QString m_clientid;
QString m_clientsecret;
QString m_server;
};
#endif //OAuthWrapper

View file

@ -0,0 +1,123 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "remoteauthasyncimageprovider.h"
#include <QQuickAsyncImageProvider>
#include <QImage>
AsyncImageResponse::AsyncImageResponse(QNetworkRequest req, QSize reqSize)
{
m_reply = m_imageLoader.get(req);
m_requestedSize = reqSize;
connect(m_reply, &QNetworkReply::finished, this, &AsyncImageResponse::onResponseFinished);
}
void AsyncImageResponse::onResponseFinished()
{
QByteArray myImageData = m_reply->readAll();
m_resultImage = QImage::fromData(myImageData);
if (m_requestedSize.isValid())
{
m_resultImage = m_resultImage.scaled(m_requestedSize);
}
emit finished();
}
QQuickTextureFactory *AsyncImageResponse::textureFactory() const
{
return QQuickTextureFactory::textureFactoryForImage(m_resultImage);
}
RemoteAuthAsyncImageProvider::RemoteAuthAsyncImageProvider()
{
}
QQuickImageResponse* RemoteAuthAsyncImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
{
QUrl iUrl=url()+"/api/friendica/remoteauth?c_url="+contacturl()+"&url="+id;
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
QNetworkRequest request(iUrl);
request.setRawHeader("Authorization", headerData.toLocal8Bit());
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute,true);
request.setUrl(iUrl);
return new AsyncImageResponse(request, requestedSize);
}
void RemoteAuthAsyncImageProvider::setContacturl(QString contacturl)
{
if (contacturl!=m_contacturl) {
m_contacturl = contacturl;
emit contacturlChanged();
}
}
void RemoteAuthAsyncImageProvider::setUrl(QString url)
{
if (url!=m_url) {
m_url = url;
emit urlChanged();
}
}
void RemoteAuthAsyncImageProvider::setLogin(QString login)
{
if (login!=m_login) {
m_login = login;
emit loginChanged();
}
}
QString RemoteAuthAsyncImageProvider::contacturl() const
{
return m_contacturl;
}
QString RemoteAuthAsyncImageProvider::url() const
{
return m_url;
}
QString RemoteAuthAsyncImageProvider::login() const
{
return m_login;
}

View file

@ -0,0 +1,95 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef REMOTEAUTHIMAGEPROVIDER_H
#define REMOTEAUTHIMAGEPROVIDER_H
#include <QObject>
#include <QQuickAsyncImageProvider>
#include <QImage>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
class AsyncImageResponse : public QQuickImageResponse
{
Q_OBJECT
public:
explicit AsyncImageResponse(QNetworkRequest req, QSize requestedSize);
QQuickTextureFactory *textureFactory() const;
public slots:
void onResponseFinished();
protected:
QNetworkAccessManager m_imageLoader;
QNetworkReply* m_reply;
QSize m_requestedSize;
QImage m_resultImage;
int m_index;
QString m_id;
QImage m_image;
};
class RemoteAuthAsyncImageProvider : public QObject, public QQuickAsyncImageProvider
{
Q_OBJECT
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
Q_PROPERTY(QString contacturl READ contacturl WRITE setContacturl NOTIFY contacturlChanged)
Q_PROPERTY(QString login READ login WRITE setLogin NOTIFY loginChanged)
public:
explicit RemoteAuthAsyncImageProvider();
QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override;
QString url() const;
QString contacturl() const;
QString login() const;
signals:
void contacturlChanged();
void urlChanged();
void loginChanged();
public slots:
void setContacturl(QString contacturl);
void setUrl(QString url);
void setLogin(QString login);
private:
QByteArray buffer;
QString m_url;
QString m_contacturl;
QString m_login;
QString bufferToString();
};
#endif // REMOTEAUTHIMAGEPROVIDER_H

861
src/common/updatenews.cpp Normal file
View file

@ -0,0 +1,861 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "updatenews.h"
#include <QHttpPart>
//#include <QTextCodec>
#include <QUrlQuery>
#include <QList>
#include <QDataStream>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QQmlEngine>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlDatabase>
#include <QSqlError>
#include <QDateTime>
UPDATENEWS *UPDATENEWS::instance()
{
static UPDATENEWS udn;
return &udn;
}
UPDATENEWS::UPDATENEWS(QObject *parent) : QObject(parent)
{
}
//void UPDATENEWS::setUrl(QString url)
//{
// if (url!=m_url) {
// m_url = url;
// xhr.setUrl(url);
// emit urlChanged(m_url);
// }
//}
void UPDATENEWS::setSyncAll(bool syncAll)
{
m_syncAll=syncAll;
}
void UPDATENEWS::setDatabase()
{
static QQmlEngine qe;
QString db_url=qe.offlineStorageDatabaseFilePath("Friendiqa");
if (!m_db.open())
{
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setDatabaseName(QUrl("file://"+db_url+".sqlite").toLocalFile());
}
if (!m_db.open())
{
qDebug() << "Error: connection with database fail " << m_db.lastError();
}
}
int UPDATENEWS::getStyle()
{
if (m_db.open()){
QSqlQuery syncquery("SELECT * FROM globaloptions",m_db);
while (syncquery.next()){
if (syncquery.value(0).toString()=="view_darkmode"){
return syncquery.value(1).toInt();
}
}
}
return 0;
}
QJsonArray UPDATENEWS::getAccounts(QString filtername, QString filtervalue){
QString filterstring="";
if (filtername!=""){
bool ok;
int filternumber = filtervalue.toInt(&ok, 10);
if(ok){
filterstring=" WHERE " + filtername + " = " + filtervalue;
}
else{
filterstring=" WHERE " + filtername + " = '" + filtervalue +"'";
}
}
QSqlQuery query("SELECT * FROM config" + filterstring + " ORDER BY isActive ASC, username ASC",m_db);
QJsonArray accountlist;
while(query.next()){
{
QJsonObject accountData;
accountData.insert("server",query.value(0).toString());
accountData.insert("username",query.value(1).toString());
accountData.insert("password",query.value(2).toString());
accountData.insert("imagestore",query.value(3).toString());
accountData.insert("isActive",query.value(7).toString());
QJsonArray m_permissions=query.value(7).toJsonArray();
accountData.insert("permissions",m_permissions);
accountData.insert("token",QString(QByteArray::fromBase64(query.value(10).toByteArray())));
QJsonDocument m_client;
if(query.value(12).toByteArray()!=""){
m_client=QJsonDocument::fromJson(QByteArray::fromBase64(query.value(12).toByteArray()));
}
accountData.insert("client",m_client.object());
accountlist.append(accountData);
}
}
query.clear();
return accountlist;
}
void UPDATENEWS::login()
{
QSqlQuery syncquery("SELECT * FROM globaloptions",m_db);
m_updateInterval=0;
syncindex=0;
synclist.clear();
while (syncquery.next()){
if (syncquery.value(0).toString()=="syncinterval"){
m_updateInterval=syncquery.value(1).toInt();
}
if (syncquery.value(0).toString().left(5)=="sync_" && syncquery.value(1).toInt()==1){
synclist.append(syncquery.value(0).toString());
}
if (syncquery.value(0).toString().left(7)=="notify_" && syncquery.value(1).toInt()==1){
notifylist.append(syncquery.value(0).toString());
}
}
QSqlQuery synctimequery("SELECT * FROM globaloptions WHERE k='lastsync'",m_db);
if (synctimequery.next()){
QSqlQuery synctimequery2("UPDATE globaloptions SET v='"+QString::number(QDateTime::currentSecsSinceEpoch()) + "' WHERE k = 'lastsync'",m_db);
if(!(synctimequery2.exec())) {qDebug()<<" synctimequery2 " << synctimequery2.lastError();}
} else {
QSqlQuery synctimequery3("INSERT INTO globaloptions(k,v) VALUES('lastsync','"+QString::number(QDateTime::currentSecsSinceEpoch()) + "')",m_db);
if(!(synctimequery3.exec())) {qDebug() << " synctimequery3 " << synctimequery3.lastError();}
}
QJsonArray acc=getAccounts();
usernamelength=acc.size();
if (usernameindex<usernamelength){
QJsonObject currentAccount =acc[usernameindex].toObject();
xhr.setAccount(currentAccount.toVariantMap());
username = currentAccount["username"].toString();
m_url=currentAccount["server"].toString();
}
}
void UPDATENEWS::startsync()
{
if (syncindex<synclist.length()){
if (synclist[syncindex]=="sync_Timeline"){
timeline();
} else if (synclist[syncindex]=="sync_Replies") {
replies();
} else if (synclist[syncindex]=="sync_DirectMessages") {
directmessages();
} else if (synclist[syncindex]=="sync_Notifications") {
notifications();
} else if (synclist[syncindex]=="sync_FriendRequests") {
friendrequests();
}else if (synclist[syncindex]=="sync_Events") {
events();
}
} else if ((syncindex==synclist.length())&&(!(usernameindex<usernamelength-1))) {
m_api="";
if(m_updateInterval!=0){
syncindex=0;
usernameindex=0;
synclist.clear();
m_db.close();
m_db.removeDatabase(m_db.connectionName());
QObject::disconnect(&xhr,SIGNAL(error(QString,QString,QString,int)),this,SLOT(showError(QString,QString,QString,int)));
emit quitapp();
//alarm.setAlarm(m_updateInterval);
m_updateInterval=0;
}
}
else{
usernameindex+=1;
login();
startsync();
}
}
void UPDATENEWS::timeline()
{
m_api="/api/statuses/friends_timeline";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
QSqlQuery query("SELECT status_id FROM news WHERE messagetype=0 AND username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){
if (query.first()){
QString lastid=query.value(0).toString();
xhr.setParam("since_id",lastid);
}
}
xhr.setParam("count","100");
xhr.get();
QObject::connect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(store(QByteArray,QString)));
QObject::connect(&xhr,SIGNAL(error(QString,QString,QString,int)),this,SLOT(showError(QString,QString,QString,int)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::replies()
{
m_api="/api/statuses/replies";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
QSqlQuery query("SELECT status_id FROM news WHERE messagetype=3 AND username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){
if (query.first()){
QString lastid=query.value(0).toString();
xhr.setParam("since_id",lastid);
}
}
xhr.setParam("count","50");
xhr.get();
QObject::connect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(store(QByteArray,QString)));
QObject::connect(&xhr,SIGNAL(error(QString,QString,QString,int)),this,SLOT(showError(QString,QString,QString,int)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::directmessages()
{
m_api="/api/direct_messages/all";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
QSqlQuery query("SELECT status_id FROM news WHERE messagetype=1 AND username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){
if (query.first()){
QString lastid=query.value(0).toString();
xhr.setParam("since_id",lastid);
}
}
xhr.get();
QObject::connect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(store(QByteArray,QString)));
QObject::connect(&xhr,SIGNAL(error(QString,QString,QString,int)),this,SLOT(showError(QString,QString,QString,int)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::notifications()
{
m_api="/api/friendica/notification";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
xhr.get();
QObject::connect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(store(QByteArray,QString)));
QObject::connect(&xhr,SIGNAL(error(QString,QString,QString,int)),this,SLOT(showError(QString,QString,QString,int)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::events()
{ m_api="/api/friendica/events";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
QSqlQuery query("SELECT id FROM events WHERE username='"+ username +"' ORDER BY id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){
if (query.first()){
QString lastid=query.value(0).toString();
xhr.setParam("since_id",lastid);
}
}
xhr.setParam("count","30");
xhr.get();
QObject::disconnect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(store(QByteArray,QString)));
QObject::connect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(storeEvents(QByteArray,QString)));
QObject::connect(&xhr,SIGNAL(error(QString,QString,QString,int)),this,SLOT(showError(QString,QString,QString,int)));
}
void UPDATENEWS::friendrequests()
{ m_api="/api/v1/follow_requests";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
xhr.get();
QObject::disconnect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(store(QByteArray,QString)));
QObject::connect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(storeFriendrequests(QByteArray,QString)));
QObject::connect(&xhr,SIGNAL(error(QString,QString,QString,int)),this,SLOT(showError(QString,QString,QString,int)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::store(QByteArray serverreply,QString apiname)
{ if (apiname!=m_api || xhr.downloadtype()!=""){} else {
QJsonDocument news;
QJsonParseError jsonerror;
news=QJsonDocument::fromJson(serverreply,&jsonerror);
if (news.isArray()){
for (int i=0; i < news.array().count();i++){
QJsonValue newsitem=news[i];
try{
if (apiname=="/api/friendica/notification"){
QSqlQuery testquery("SELECT status_id FROM news WHERE status_id=" + QString::number(newsitem["id"].toInt()) + " AND messagetype=2 AND username='"+ username +"'",m_db);
if (testquery.first()) {continue;}
}
QSqlQuery query(m_db);
query.prepare("INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,"
"geo,favorited,uid,statusnet_html,statusnet_conversation_id,friendica_activities,friendica_activities_self,attachments,friendica_owner) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
query.bindValue(0,username);
query.bindValue(1,"0");
query.bindValue(2, newsitem["text"].toString().toUtf8().toBase64());
QString sourcedate=newsitem["created_at"].toString();
QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
query.bindValue(3,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
if(newsitem["in_reply_to_status_id"]!=QJsonValue::Null){query.bindValue(4, newsitem["in_reply_to_status_id"].toInt());}
query.bindValue(5,newsitem["source"]);
query.bindValue(6,newsitem["id"].toInt());
if(newsitem["in_reply_to_user_id"]!=QJsonValue::Null){ query.bindValue(7,newsitem["in_reply_to_user_id"].toInt());}
QJsonObject geo;
geo["external_url"]=newsitem["external_url"];
query.bindValue(8,QJsonDocument(geo).toJson(QJsonDocument::Compact).toStdString().c_str());
//query.bindValue(8,newsitem["geo"]);
query.bindValue( 9, newsitem["favorited"].toInt());
query.bindValue(10, newsitem["user"]["id"].toInt());
//if (newsitem["friendica_title"]!="") {
// QString friendicaHtml="<b>" + newsitem["friendica_title"].toString() +"</b><br><br>"+newsitem["friendica_html"].toString();
// query.bindValue(11, friendicaHtml.toUtf8().toBase64());}
//else{
query.bindValue(11, newsitem["friendica_html"].toString().toUtf8().toBase64());//}
if (newsitem["statusnet_conversation_id"].isDouble()){
query.bindValue(12, newsitem["statusnet_conversation_id"].toInt());
}else{query.bindValue(12, newsitem["statusnet_conversation_id"].toString());}
QJsonArray likeArray;QJsonArray dislikeArray;QJsonArray attendyesArray;QJsonArray attendnoArray;QJsonArray attendmaybeArray;
if (newsitem.toObject().contains("friendica_activities")){
for (int a=0; a < newsitem["friendica_activities"]["like"].toArray().count();a++){
likeArray.append(newsitem["friendica_activities"]["like"][a]["url"].toString());
}
for (int b=0; b < newsitem["friendica_activities"]["dislike"].toArray().count();b++){
dislikeArray.append(newsitem["friendica_activities"]["dislike"][b]["url"].toString());
}
for (int c=0; c < newsitem["friendica_activities"]["attendyes"].toArray().count();c++){
attendyesArray.append(newsitem["friendica_activities"]["attendyes"][c]["url"].toString());
}
for (int d=0; d < newsitem["friendica_activities"]["attendno"].toArray().count();d++){
attendnoArray.append(newsitem["friendica_activities"]["attendno"][d]["url"].toString());
}
for (int e = 0; e < newsitem["friendica_activities"]["attendmaybe"].toArray().count();e++){
attendmaybeArray.append(newsitem["friendica_activities"]["attendmaybe"][e]["url"].toString());
}
}
QJsonArray friendica_activities; friendica_activities={likeArray,dislikeArray,attendyesArray,attendnoArray,attendmaybeArray};
QJsonDocument activities; activities.setArray(friendica_activities);
query.bindValue(13,activities.toJson(QJsonDocument::Compact).toBase64());
query.bindValue(14,"[]");
if (newsitem["attachments"]!=QJsonValue::Undefined){
query.bindValue(15, QJsonDocument(newsitem["attachments"].toArray()).toJson(QJsonDocument::Compact).toBase64());
}else {
query.bindValue(15, "");
}
if (newsitem["friendica_author"]!=QJsonValue::Undefined){
query.bindValue(16, newsitem["friendica_author"]["url"]);
}else {
query.bindValue(16, newsitem["user"]["url"]);
}
if (apiname=="/api/statuses/replies"){
query.bindValue(1,"3");
}
if (apiname == "/api/direct_messages/all"){
query.bindValue(1,"1");
query.bindValue(5,"Friendica");
query.bindValue(6,newsitem["id"].toInt());
if(newsitem["recipient"]["id"]!=QJsonValue::Null){ query.bindValue(7,newsitem["recipient"]["id"].toInt());}
query.bindValue(10, newsitem["sender_id"].toInt());
query.bindValue(11, newsitem["text"].toString().toUtf8().toBase64());
if(newsitem["friendica_parent_uri"]!=QJsonValue::Null){ query.bindValue(12,newsitem["friendica_parent_uri"]);}
query.bindValue(16, newsitem["sender"]["url"]);
}
if (apiname == "/api/friendica/notification"){
query.bindValue(1,"2");
query.bindValue(3,QDateTime::fromString(newsitem["date"].toString(),"yyyy-MM-dd hh:mm:ss").toMSecsSinceEpoch());
query.bindValue(5,"Friendica");
QJsonObject cleancontact= findNotificationContact(newsitem["url"].toString());
query.bindValue(10, cleancontact["id"].toInt());
query.bindValue(11, newsitem["msg_html"].toString().toUtf8().toBase64());
if(newsitem["parent"]!=QJsonValue::Null){ query.bindValue(12,newsitem["parent"]);}
query.bindValue(16, newsitem["url"]);
}
if(!(query.exec())) {qDebug()<< "store news " << query.lastError();}
// notifications
if (apiname=="/api/statuses/friends_timeline"){
if(notifylist.contains("notify_Timeline")){
alarm.notify("Home: "+ newsitem["user"]["name"].toString(),newsitem["text"].toString(),0);
}
}
if (apiname=="/api/statuses/replies"){
if(notifylist.contains("notify_Replies")){
alarm.notify("Replies: "+newsitem["user"]["name"].toString(),newsitem["text"].toString(),1);
}
}
if (apiname=="/api/direct_messages/all"){
if(notifylist.contains("notify_DirectMessages")){
alarm.notify("DirectMessage: "+newsitem["sender"]["name"].toString(),newsitem["text"].toString(),2);
}
}
if (apiname=="/api/friendica/notification"){
if(notifylist.contains("notify_Notifications")){
alarm.notify("Notification: "+newsitem["name"].toString(),newsitem["text"].toString(),3);
}
}
}catch(...){
//qDebug() << "Friendiqasync Error inserting news" << newsitem["text"].toString() << " " << newsitem.toString();
}
}
QList<QJsonValue> newcontacts=findNewContacts(news);
emit this->success(m_api);
if (newcontacts.size()>0){
updateContacts(newcontacts);
startImagedownload("contactlist");
} else {
if((m_updateInterval!=0) && m_syncAll){
syncindex+=1;
startsync();
}
}
}
else {
qDebug()<< m_api <<username << "Friendiqa updatenews error " << serverreply ;
//emit this->error(m_api,QTextCodec::codecForName("utf-8")->toUnicode(serverreply));
emit this->error(m_api,QString(serverreply));
if(m_syncAll){
syncindex+=1;
startsync();
}
}
}
}
void UPDATENEWS::updateImageLocation(QString downloadtype,QString imageurl, QString filename, int index){
if (downloadtype=="contactlist"){
QSqlQuery testquery("SELECT profile_image FROM contacts WHERE profile_image_url ='"+imageurl+ "' AND username = '" +username+"'",m_db);
testquery.first();
QSqlQuery query("UPDATE contacts SET profile_image='"+ filename +"' WHERE profile_image_url ='"+imageurl+ "' AND username = '" +username+"'",m_db);
if(!(query.exec())) {qDebug()<< "updateImagelocation " << query.lastError();}
if (index==(newcontactnames.length()-1)){
newcontactnames.clear();
newcontactimagelinks.clear();
if((m_updateInterval!=0) && m_syncAll){
syncindex+=1;
startsync();
}
}
}
else if (downloadtype=="friendrequests"){
QSqlQuery testquery("SELECT avatar_static FROM friendshiprequests WHERE avatar ='"+imageurl+ "' AND username = '" +username+"'",m_db);
testquery.first();
QSqlQuery query("UPDATE friendshiprequests SET avatar_static='"+ filename +"' WHERE avatar ='"+imageurl+ "' AND username = '" +username+"'",m_db);
if(!(query.exec())) {qDebug()<< "update friendrequests Imagelocation " << query.lastError();}
if (index==(newcontactnames.length()-1)){
newcontactnames.clear();
newcontactimagelinks.clear();
if((m_updateInterval!=0) && m_syncAll){
syncindex+=1;
startsync();
}
}
}
}
QJsonObject UPDATENEWS::findNotificationContact(QString contacturl){
QSqlQuery query("SELECT id,url FROM contacts WHERE url='"+contacturl+"' AND username='"+ username+"'",m_db);
query.first();
QJsonObject contact{
{"id", query.value(0).toInt()},
{"url", query.value(1).toString()}
};
return contact;
}
QList <QJsonValue> UPDATENEWS::findNewContacts(QJsonDocument news){
QSqlQuery query("SELECT profile_image_url FROM contacts",m_db);
QList<QString> imageurls;
while (query.next()){
imageurls.append(query.value(0).toString());
}
QList<QJsonValue> newcontacts;
for (int i=0; i<news.array().count();i++){
//main contacts
if (news[i].toObject().contains("sender") ){
if(imageurls.contains(news[i]["sender"]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["sender"]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["sender"]);
newcontactimagelinks.append(news[i]["sender"]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["sender"]["screen_name"].toString());
}
}
if (news[i].toObject().contains("user") ){
if(imageurls.contains(news[i]["user"]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["user"]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["user"]);
newcontactimagelinks.append(news[i]["user"]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["user"]["screen_name"].toString());
}
}
//like/dislike contacts
if (news[i].toObject().contains("friendica_activities") ){
for (int a=0; a < news[i]["friendica_activities"]["like"].toArray().count();a++){
if(imageurls.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["friendica_activities"]["like"][a]);
newcontactimagelinks.append(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["friendica_activities"][a]["screen_name"].toString());
}
}
for (int b=0; b < news[i]["friendica_activities"]["dislike"].toArray().count();b++){
if(imageurls.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["friendica_activities"]["dislike"][b]);
newcontactimagelinks.append(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["friendica_activities"][b]["screen_name"].toString());
}
}
}
//owner contacts
if (news[i].toObject().contains("friendica_author") ){
if(imageurls.contains(news[i]["friendica_author"]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["friendica_owner"]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["friendica_author"]);
newcontactimagelinks.append(news[i]["friendica_author"]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["friendica_author"]["screen_name"].toString());
}
}
}
return newcontacts;
}
void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
qint64 currentTime =QDateTime::currentMSecsSinceEpoch();
for (int i=0; i < contacts.count();i++){
QJsonValue contact=contacts[i];
QSqlQuery query(m_db);
try{
QSqlQuery testquery("SELECT url FROM contacts WHERE username='"+ username +"' AND url='" + contact["url"].toString() +"'",m_db);
if (testquery.first()){
query.prepare("UPDATE contacts SET id=?, name=?, screen_name=?, location=?,imageAge=?,"
"profile_image_url=?, description=?, protected=?, followers_count=?,"
"friends_count=?, created_at=?, favourites_count=?, utc_offset=?, time_zone=?, statuses_count=?,"
"following=?, verified=?, statusnet_blocking=?, notifications=?, statusnet_profile_url=?, cid=?, network=?, timestamp=? "
" WHERE username='"+ username +"' AND url='" + contact["url"].toString() +"'");
query.bindValue(0, contact["id"].toInt());
query.bindValue(1, contact["name"].toString().toUtf8().toBase64());
query.bindValue(2, contact["screen_name"]);
query.bindValue(3, contact["location"]);
query.bindValue(4, currentTime);
query.bindValue(5, contact["profile_image_url"].toString().section('?',0,0));
if(contact["description"].isNull() ){query.bindValue(6,"");}else{query.bindValue(6, contact["description"].toString().toUtf8().toBase64());}
query.bindValue(7,contact["protected"].toBool());
query.bindValue(8,contact["followers_count"].toInt());
query.bindValue(9,contact["friends_count"].toInt());
QString sourcedate=contact["created_at"].toString();
QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
query.bindValue(10,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
query.bindValue(11,contact["favorites_count"].toInt());
query.bindValue(12,contact["utc_offset"].toInt());
query.bindValue(13,contact["time_zone"].toString());
query.bindValue(14,contact["statuses_count"].toInt());
query.bindValue(15,contact["following"].toBool());
query.bindValue(16,contact["verfied"].toBool());
query.bindValue(17,contact["statusnet_blocking"].toBool());
query.bindValue(18,contact["notifications"].toBool());
query.bindValue(19,contact["statusnet_profile_url"]);
query.bindValue(20,contact["cid"].toInt());
query.bindValue(21,contact["network"]);
qint64 timestamp=0;
QString timestamphelper=contact["profile_image_url"].toString();
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){}
query.bindValue(22,timestamp);
}
else{
query.prepare("INSERT INTO contacts (username, id, name, screen_name, location,imageAge,"
"profile_image_url, description, profile_image, url, protected, followers_count,"
"friends_count, created_at, favourites_count, utc_offset, time_zone, statuses_count,"
"following, verified, statusnet_blocking, notifications, statusnet_profile_url, cid, network, isFriend, timestamp)"
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
query.bindValue(0,username);
query.bindValue(1, contact["id"].toInt());
query.bindValue(2, contact["name"].toString().toUtf8().toBase64());
query.bindValue(3, contact["screen_name"]);
query.bindValue(4, contact["location"]);
query.bindValue(5, currentTime);
query.bindValue(6, contact["profile_image_url"].toString().section('?',0,0));
if(contact["description"].isNull() ){query.bindValue(7,"");}else{query.bindValue(7, contact["description"].toString().toUtf8().toBase64());}
query.bindValue(8,"none");
query.bindValue(9, contact["url"].toString());
query.bindValue(10,contact["protected"].toBool());
query.bindValue(11,contact["followers_count"].toInt());
query.bindValue(12,contact["friends_count"].toInt());
QString sourcedate=contact["created_at"].toString();
QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
query.bindValue(13,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
query.bindValue(14,contact["favorites_count"].toInt());
query.bindValue(15,contact["utc_offset"].toInt());
query.bindValue(16,contact["time_zone"].toString());
query.bindValue(17,contact["statuses_count"].toInt());
query.bindValue(18,contact["following"].toBool());
query.bindValue(19,contact["verified"].toBool());
query.bindValue(20,contact["statusnet_blocking"].toBool());
query.bindValue(21,contact["notifications"].toBool());
query.bindValue(22,contact["statusnet_profile_url"]);
query.bindValue(23,contact["cid"].toInt());
query.bindValue(24,contact["network"]);
query.bindValue(25, 0);
qint64 timestamp=0;
QString timestamphelper=contact["profile_image_url"].toString();
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){}
query.bindValue(26,timestamp);
}
if(!(query.exec())) {qDebug()<< "updatecontacts " << query.lastError();}
} catch(...){
qDebug() << "Friendiqasync Error inserting contact" << contact["screen_name"] << " " << contact.toString();
}
}
}
void UPDATENEWS::storeFriendrequests(QByteArray serverreply,QString apiname)
{ if (apiname!=m_api || xhr.downloadtype()!=""){} else {
QJsonDocument friendrequests;
QJsonParseError jsonerror;
friendrequests=QJsonDocument::fromJson(serverreply,&jsonerror);
if (friendrequests.isArray()){
QSqlQuery imagequery("SELECT avatar FROM friendshiprequests",m_db);
QList<QString> imageurls;
while (imagequery.next()){
imageurls.append(imagequery.value(0).toString());
}
for (int i=0; i < friendrequests.array().count();i++){
QJsonValue friendrequestitem=friendrequests[i];
try{
QSqlQuery testquery("SELECT url FROM friendshiprequests WHERE username='"+ username +"' AND url='" + friendrequestitem["url"].toString() +"'",m_db);
QSqlQuery query(m_db);
if (testquery.first()){
query.prepare("UPDATE friendshiprequests SET id=?, usernamef=?, acct=?, display_name=?,locked=?,"
"bot=?, discoverable=?, groupf=?, created_at=?,"
"note=?, avatar=?, header=?, header_static=?, followers_count=?,"
"following_count=?, statuses_count=?, last_status_at=?, emojis=?, fields=? "
" WHERE username='"+ username +"' AND url='" + friendrequestitem["url"].toString() +"'");
query.bindValue(0, friendrequestitem["id"].toInt());
query.bindValue(1, friendrequestitem["username"]);
query.bindValue(2, friendrequestitem["acct"]);
query.bindValue(3, friendrequestitem["display_name"].toString().toUtf8().toBase64());
query.bindValue(4, friendrequestitem["locked"].toBool());
query.bindValue(5, friendrequestitem["bot"].toBool());
query.bindValue(6, friendrequestitem["discoverable"].toBool());
query.bindValue(7, friendrequestitem["group"].toBool());
query.bindValue(8, QDateTime::fromString(friendrequestitem["created_at"].toString(),Qt::ISODate).toMSecsSinceEpoch() );
query.bindValue(9, friendrequestitem["note"].toString().toUtf8().toBase64());
query.bindValue(10, friendrequestitem["avatar"]);
query.bindValue(11, friendrequestitem["header"]);
query.bindValue(12, friendrequestitem["header_static"]);
query.bindValue(13, friendrequestitem["followers_count"].toInt());
query.bindValue(14, friendrequestitem["following_count"].toInt());
query.bindValue(15, friendrequestitem["statuses_count"].toInt());
query.bindValue(16, QDateTime::fromString(friendrequestitem["last_status_at"].toString(),Qt::ISODate).toMSecsSinceEpoch() );
query.bindValue(17, friendrequestitem["emojis"].toString().toUtf8().toBase64());
query.bindValue(18, friendrequestitem["fields"].toString().toUtf8().toBase64());
}
else{
query.prepare("INSERT INTO friendshiprequests (username, id, usernamef, acct, display_name, locked,"
" created_at, followers_count, following_count, statuses_count, note, url, avatar, avatar_static, "
"header, header_static, emojis, moved, fields, bot, groupf, discoverable, last_status_at) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
query.bindValue(0, username);
query.bindValue(1, friendrequestitem["id"].toInt());
query.bindValue(2, friendrequestitem["username"].toString());
query.bindValue(3, friendrequestitem["acct"].toString());
query.bindValue(4, friendrequestitem["display_name"].toString().toUtf8().toBase64());
query.bindValue(5, friendrequestitem["locked"].toBool());
query.bindValue(6, QDateTime::fromString(friendrequestitem["created_at"].toString(),Qt::ISODate).toMSecsSinceEpoch());
query.bindValue(7, friendrequestitem["followers_count"].toInt());
query.bindValue(8, friendrequestitem["following_count"].toInt());
query.bindValue(9, friendrequestitem["statuses_count"].toInt());
query.bindValue(10, friendrequestitem["note"].toString().toUtf8().toBase64());
query.bindValue(11, friendrequestitem["url"].toString());
query.bindValue(12, friendrequestitem["avatar"].toString());
query.bindValue(13, "");
query.bindValue(14, friendrequestitem["header"].toString());
query.bindValue(15, friendrequestitem["header_static"].toString());
query.bindValue(16, friendrequestitem["emojis"].toString().toUtf8().toBase64());
query.bindValue(17, "false");
query.bindValue(18, friendrequestitem["fields"].toString().toUtf8().toBase64());
query.bindValue(19, friendrequestitem["bot"].toBool());
query.bindValue(20, friendrequestitem["group"].toBool());
query.bindValue(21, friendrequestitem["discoverable"].toBool());
query.bindValue(22, QDateTime::fromString(friendrequestitem["last_status_at"].toString(),Qt::ISODate).toMSecsSinceEpoch());
if(notifylist.contains("notify_FriendRequests")){
alarm.notify("Friend Request: "+ friendrequestitem["acct"].toString(),friendrequestitem["note"].toString(),0);
}
}
if(!(query.exec())) {qDebug()<< "friendrequestitem error " << query.lastError() << " " << query.lastQuery();}
} catch(...){
qDebug() << "Friendiqasync Error inserting friendrequestitem" << friendrequestitem["acct"] << " " ;
}
if(imageurls.contains(friendrequestitem["avatar"].toString() )){
}
else{
newcontactimagelinks.append(friendrequestitem["avatar"].toString());
newcontactnames.append(friendrequestitem["username"].toString());
}
}
if (newcontactimagelinks.length()>0){
startImagedownload("friendrequests");
}else{
if((m_updateInterval!=0) && m_syncAll){
syncindex+=1;
startsync();
}
}
}
}
QObject::disconnect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(storeFriendrequests(QByteArray,QString)));
}
void UPDATENEWS::storeEvents(QByteArray serverreply,QString apiname)
{ if (apiname!=m_api || xhr.downloadtype()!=""){} else {
QJsonDocument events;
QJsonParseError jsonerror;
events=QJsonDocument::fromJson(serverreply,&jsonerror);
if (events.isArray()){
for (int i=0; i < events.array().count();i++){
QJsonValue eventitem=events[i];
try{
QSqlQuery query(m_db);
query.prepare("INSERT INTO events (username,id,cid,start,end,title,uri,desc,location,type,nofinish,adjust,ignore,permissions) " "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
query.bindValue(0,username);
query.bindValue(1,eventitem["id"].toInt());
query.bindValue(2,eventitem["cid"].toInt());
QString sourcedateStart="";
if (eventitem["start_time"].toString()!=""){
sourcedateStart=eventitem["start_time"].toString();}else{
sourcedateStart=eventitem["startTime"].toString();
};
query.bindValue(3,QDateTime::fromString(sourcedateStart,Qt::ISODate).toMSecsSinceEpoch() );
QString sourcedateEnd="";
if (eventitem["end_time"].toString()!=""){
sourcedateEnd=eventitem["end_time"].toString();} else{
sourcedateEnd=eventitem["endTime"].toString();
}
if(QDateTime::fromString(sourcedateEnd,Qt::ISODate).toMSecsSinceEpoch()>QDateTime::fromString(sourcedateStart,Qt::ISODate).toMSecsSinceEpoch()){
//check if end is later than start
query.bindValue(4,QDateTime::fromString(sourcedateEnd,Qt::ISODate).toMSecsSinceEpoch() );
} else {
query.bindValue(4,0 );
}
query.bindValue(4,QDateTime::fromString(sourcedateEnd,Qt::ISODate).toMSecsSinceEpoch() );
query.bindValue(5,eventitem["name"].toString());
query.bindValue(6,eventitem["uri"].toString());
query.bindValue(7,eventitem["desc"].toString().toUtf8().toBase64());
query.bindValue(8,eventitem["place"].toString());
query.bindValue(9,eventitem["type"].toString());
query.bindValue(10,eventitem["nofinish"].toInt());
query.bindValue(11,eventitem["adjust"].toInt());
query.bindValue(12,eventitem["ignore"].toInt());
QJsonArray permissions; permissions={eventitem["allow_cid"].toString().replace("<","[").replace(">","]"),eventitem["allow_gid"].toString().replace("<","[").replace(">","]"),eventitem["deny_cid"].toString().replace("<","[").replace(">","]"),eventitem["deny_gid"].toString().replace("<","[").replace(">","]")};
QJsonDocument permissionDocument; permissionDocument.setArray(permissions);
query.bindValue(13,permissionDocument.toJson(QJsonDocument::Compact));
if(!(query.exec())) {qDebug()<< "store events " << query.lastError();}
} catch(...){
qDebug() << "Friendiqasync Error event" << eventitem["name"];
}
}
emit this->success(m_api);
}
}
if(notifylist.contains("notify_Events")){
QSqlQuery eventnotifyquery("SELECT start,title FROM events WHERE (start BETWEEN " + QString::number(QDateTime::currentDateTime().toMSecsSinceEpoch()) + " AND "+QString::number(QDateTime::currentDateTime().toMSecsSinceEpoch()+(m_updateInterval*119*1000))+") AND username='"+ username +"'",m_db);
while (eventnotifyquery.next()) {
alarm.notify("Event: "+ QDateTime::fromMSecsSinceEpoch(eventnotifyquery.value(0).toLongLong()).toString("dd.MM.yyyy hh:mm"),eventnotifyquery.value(1).toString(),1);
}
}
if((m_updateInterval!=0) && m_syncAll){
syncindex+=1;
startsync();
}
QObject::disconnect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(storeEvents(QByteArray,QString)));
}
void UPDATENEWS::startImagedownload(QString downloadtype)
{
xhr.setDownloadtype(downloadtype );
xhr.setFilelist(newcontactimagelinks);
xhr.setContactlist(newcontactnames);
xhr.getlist();
}
void UPDATENEWS::showError(QString data, QString url,QString api, int code )
{
emit this->error(api,data);
if (api!=m_api || xhr.downloadtype()!=""){} else{
if((m_updateInterval!=0) && m_syncAll){
syncindex+=1;
startsync();
}
}
}

99
src/common/updatenews.h Normal file
View file

@ -0,0 +1,99 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef UPDATENEWS_H
#define UPDATENEWS_H
#include <QObject>
#include <QJsonObject>
#include <QJsonArray>
#include <QSqlDatabase>
#include "xhr.h"
#include "alarm.h"
//#include "AndroidNative/systemdispatcher.h"
class UPDATENEWS : public QObject
{
Q_OBJECT
public:
static UPDATENEWS *instance();
explicit UPDATENEWS(QObject *parent = 0);
signals:
void success(QString api);
void error(QString api, QString content);
void quitapp();
public slots:
void setSyncAll(bool syncAll);
void setDatabase();
int getStyle();
void login();
void timeline();
void replies();
void startsync();
void directmessages();
void notifications();
void friendrequests();
void events();
void startImagedownload(QString downloadtype);
void updateImageLocation(QString downloadtype,QString imageurl, QString filename, int index);
void store(QByteArray serverreply,QString apiname);
void storeFriendrequests(QByteArray serverreply,QString apiname);
void storeEvents(QByteArray serverreply,QString apiname);
void showError(QString data, QString url,QString api, int code);
QJsonArray getAccounts(QString filtername="",QString filtervalue="");
private:
QString m_api;
QString m_url;
QString username;
bool m_syncAll;
int syncindex;
int usernameindex;
int usernamelength;
QSqlDatabase m_db;
QList<QString> synclist;
QList <QString> notifylist;
QList<QJsonValue> findNewContacts(QJsonDocument news);
QJsonObject findNotificationContact(QString imagelink);
int m_updateInterval;
void updateContacts(QList<QJsonValue> contacts);
XHR xhr;
ALARM alarm;
QList<QString> newcontactimagelinks;
QList<QString> newcontactnames;
};
#endif // UPDATENEWS_H

View file

@ -0,0 +1,143 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "uploadableimage.h"
#include <QBuffer>
#include <QDebug>
#include <QFileInfo>
#include <QUrl>
#include <QTransform>
void UploadableImage::setAngle(const int &b) {
if (b != m_angle) {
m_angle = b;
//qDebug() << "UploadableImage::setAngle : " << m_angle;
if (m_angle==0) {
emit angleChanged();
return;
}
}
}
void UploadableImage::setSource(const QString &a) {
if (a != m_source) {
m_source = a;
//m_base64 = "";
m_mimetype = "";
m_filename = "";
//qDebug() << "UploadableImage::setSource : " << m_source;
if (m_source=="") {
emit sourceChanged();
//emit base64Changed();
emit mimetypeChanged();
emit filenameChanged();
return;
}
QImage fullimage = QImage(QUrl(m_source).toLocalFile());
if (m_angle!=0){
QTransform transform;
transform.rotate(qreal(m_angle));
fullimage=fullimage.transformed(transform);
}
if (fullimage.width() > 800 || fullimage.height() > 800) {
if (fullimage.width() > fullimage.height()) {
m_image = fullimage.scaledToWidth(800);
} else {
m_image = fullimage.scaledToHeight(800);
}
} else {
m_image = fullimage;
}
//qDebug() << "UploadableImage::setSource : " << m_image.width() << "x" << m_image.height();
emit sourceChanged();
QFileInfo fi(m_source);
m_filename = fi.fileName();
emit filenameChanged();
QString filetype = fi.suffix().toUpper();
if (filetype!="PNG" && filetype!="JPG") {
filetype = "JPG";
}
//qDebug() << "UploadableImage::setSource : " << "Saving as " << filetype;
m_mimetype = "image/"+filetype.toLower();
emit mimetypeChanged();
/*
QByteArray byteArray;
QBuffer buffer(&byteArray);
m_image.save(&buffer, filetype.toLatin1().constData());
QString b64 = QString::fromLatin1(byteArray.toBase64().data());
for(int k=0; k<b64.length(); k+=76) {
m_base64 += b64.mid(k,76) + "\n";
}
m_base64 = m_base64.trimmed();
emit base64Changed();
*/
}
}
QString UploadableImage::source() const {
return m_source;
}
int UploadableImage::angle() const{
return m_angle;
}
//QString UploadableImage::base64() const {
// return m_base64;
//}
QString UploadableImage::filename() const {
return m_filename;
}
QString UploadableImage::mimetype() const {
return m_mimetype;
}
QByteArray UploadableImage::bytes() {
QByteArray byteArray;
QBuffer buffer(&byteArray);
m_image.save(&buffer, "PNG");
return byteArray;
}

View file

@ -0,0 +1,75 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef UPLOADABLEIMAGE_H
#define UPLOADABLEIMAGE_H
#include <QObject>
#include <QQuickItem>
#include <QImage>
class UploadableImage : public QObject
{
Q_OBJECT
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(int angle READ angle WRITE setAngle NOTIFY angleChanged)
//Q_PROPERTY(QString base64 READ base64 NOTIFY base64Changed)
Q_PROPERTY(QString filename READ filename NOTIFY filenameChanged)
Q_PROPERTY(QString mimetype READ mimetype NOTIFY mimetypeChanged)
Q_PROPERTY(QByteArray bytes READ bytes)
public:
void setSource(const QString &a);
void setAngle(const int &b);
QString source() const;
int angle() const;
//QString base64() const;
QString filename() const;
QString mimetype() const;
QByteArray bytes();
signals:
void sourceChanged();
void angleChanged();
//void base64Changed();
void filenameChanged();
void mimetypeChanged();
private:
QString m_source;
QImage m_image;
int m_angle;
//QString m_base64;
QString m_filename;
QString m_mimetype;
};
#endif // UPLOADABLEIMAGE_H

445
src/common/xhr.cpp Normal file
View file

@ -0,0 +1,445 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "xhr.h"
#include <QHttpPart>
//#include <QTextCodec>
#include <QUrlQuery>
#include <QList>
#include <QDataStream>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include "uploadableimage.h"
XHR *XHR::instance()
{
static XHR xhr;
return &xhr;
}
XHR::XHR(QObject *parent) : QObject(parent)
{
//request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
}
void XHR::setUrl(QString url)
{
if (url!=m_url) {
m_url = url;
emit urlChanged();
}
}
void XHR::setApi(QString api)
{
if (api!=m_api) {
m_api = api;
emit apiChanged();
}
}
void XHR::setLogin(QString login)
{
if (login!=m_login) {
m_login = login;
m_token="";
emit loginChanged();
}
}
void XHR::setAccount(QVariantMap account)
{
clearParams();
if (account["password"].toString() !=""){
setLogin(account["username"].toString()+":"+QByteArray::fromBase64(account["password"].toByteArray()));
}
else if (account["token"].toString() !="" && !account["token"].isNull()){
setToken(account["token"].toString());
}
setUrl(account["server"].toString());
setImagedir(account["imagestore"].toString());
m_account = account;
emit accountChanged();
}
void XHR::setToken(QString token)
{
if (token!=m_token) {
m_token = token;
m_login="";
emit tokenChanged();
}
}
void XHR::setFilename(QString filename)
{
if (filename!=m_filename) {
m_filename = filename;
emit filenameChanged();
}
}
void XHR::setContactlist(QList<QString> contactlist)
{
if (contactlist!=m_contactlist) {
m_contactlist = contactlist;
emit contactlistChanged();
}
}
void XHR::setFilelist(QList<QString> filelist)
{
if (filelist!=m_filelist) {
m_filelist = filelist;
emit filelistChanged();
}
}
void XHR::setImagedir(QString imagedir)
{
if (imagedir!=m_imagedir) {
m_imagedir = imagedir;
emit imagedirChanged();
}
}
void XHR::setDownloadtype(QString downloadtype)
{
if (downloadtype!=m_downloadtype) {
m_downloadtype = downloadtype;
emit downloadtypeChanged();
}
}
QString XHR::url() const
{
return m_url;
}
QString XHR::api() const
{
return m_api;
}
QString XHR::login() const
{
return m_login;
}
QString XHR::token() const
{
return m_token;
}
QVariantMap XHR::account() const
{
return m_account;
}
QString XHR::filename() const
{
return m_filename;
}
QList<QString> XHR::contactlist() const
{
return m_contactlist;
}
QList<QString> XHR::filelist() const
{
return m_filelist;
}
QString XHR::imagedir() const
{
return m_imagedir;
}
QString XHR::downloadtype() const
{
return m_downloadtype;
}
void XHR::setParam(QString name, QString value)
{
params.insert(name, value);
}
void XHR::setImageFileParam(QString name, QString url)
{
files.insert(name, url);
}
void XHR::clearParams()
{
files.clear();
params.clear();
}
void XHR::download()
{
QUrl requrl(m_url);
QNetworkRequest request;
if(m_downloadtype=="picturelist"){
if(m_login!=""){
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
} else{
QString headerData = "Bearer " + m_token;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
}
}
request.setUrl(requrl);
reply = manager.get(request);
reply->ignoreSslErrors();
connect(reply, &QNetworkReply::readyRead,this, &XHR::onReadyRead);
//connect(reply,SIGNAL(downloadProgress(qint64,qint64)), this,SLOT(updateDownloadProgress(qint64,qint64)));
connect(reply, &QNetworkReply::finished,this, &XHR::onRequestFinished);
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
}
void XHR::get()
{
QUrlQuery query;
//qDebug() << "get";
QHashIterator<QString, QString> i(params);
while(i.hasNext()) {
i.next();
//qDebug() << i.key() << "value" << i.value();
query.addQueryItem(i.key(), i.value());
}
QUrl requrl(m_url+m_api);
requrl.setQuery(query);
QNetworkRequest request;
if(m_login!=""){
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
} else if (m_token!=""){
QString headerData = "Bearer " + m_token;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
}
request.setUrl(requrl);
reply = manager.get(request);
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
//connect(reply,SIGNAL(downloadProgress(qint64,qint64)), this,SLOT(updateDownloadProgress(qint64,qint64)));
connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
}
void XHR::getlist()
{
if(dlindex < m_filelist.size()) {
QString cleanfilename;
if (m_downloadtype=="contactlist" || m_downloadtype=="friendrequests" ){
cleanfilename = m_contactlist.at(dlindex)+"-"+ m_filelist.at(dlindex).section('/',-1).section('?',0,0);
XHR::setFilename(imagedir()+"contacts/"+cleanfilename);
XHR::setUrl(m_filelist.at(dlindex));}
else {
XHR::setUrl(m_filelist.at(dlindex));}
//qDebug() << "start download" << m_url;
XHR::download();
} else {dlindex=0;m_downloadtype="";m_contactlist.clear();m_filelist.clear();}
}
void XHR::post()
{
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHashIterator<QString, QString> iparams(params);
while(iparams.hasNext()) {
iparams.next();
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + iparams.key() + "\""));
textPart.setBody(iparams.value().toUtf8());
multiPart->append(textPart);
}
UploadableImage uimg;
if (files.contains("media")){
uimg.setAngle(files.value("angle").toInt());
uimg.setSource(files.value("media"));
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(uimg.mimetype()));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"media\"; filename=\""+uimg.filename()+"\""));
imagePart.setBody(uimg.bytes());
multiPart->append(imagePart);
}
QNetworkRequest request;
if(m_login!=""){
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
} else if (m_token!=""){
QString headerData = "Bearer " + m_token;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
}
request.setUrl(m_url+m_api);
reply = manager.post(request, multiPart);
qDebug() << "\t request sent";
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
connect(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
}
void XHR::postJSON()
{
if (params.contains("JSON")){
QByteArray mJSON=params.value("JSON").toUtf8();
QNetworkRequest request;
if(m_login!=""){
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
} else if (m_token!=""){
QString headerData = "Bearer " + m_token;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
}
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json; charset=UTF-8");
request.setUrl(m_url+m_api);
reply = manager.post(request, mJSON);
qDebug() << "\t request sent";
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
qDebug() << "\t reply signals connected";
}
}
void XHR::onReplyError(QNetworkReply::NetworkError code)
{
qDebug() << code;
if(downloadtype()!="contactlist"){emit this->error( bufferToString(), m_url,m_api, (int) code);}
buffer.clear();
reply->deleteLater();
if((downloadtype()=="contactlist")||(downloadtype()=="picturelist")){dlindex=dlindex+1;XHR::getlist();}
}
void XHR::onReplySuccess()
{
qDebug() << "!";
QHashIterator<QString, QString> i(params);
// while(i.hasNext()) {
// i.next();
// //qDebug() << i.key()<< " " << i.value();
// }
//emit this->success(buffer, m_api);
emit success(buffer, m_api);
//emit this->error(m_downloadtype,m_url,m_api,1);
buffer.clear();
// reply->deleteLater();
}
void XHR::onRequestFinished()
{
// Save the file here
//qDebug() << "buffer " << buffer;
if (buffer.isNull()){qDebug() << "File empty"<<m_url;
buffer.clear();
emit this->error(m_downloadtype,m_url,m_api,1);
}
else if (m_downloadtype=="picturelist") {
QJsonDocument jsonResponse = QJsonDocument::fromJson(buffer);
QJsonObject jsonObject = jsonResponse.object();
int arraystart=buffer.indexOf("{\"data\":\"")+8;
int arraylength=buffer.indexOf('"',9)-arraystart;
QByteArray b64=buffer.mid(arraystart,arraylength);
QString helpfilename=jsonObject["filename"].toString();
QString helpfile=helpfilename.left(helpfilename.lastIndexOf("."));
QString filesuffix="";
if (jsonObject["type"].toString()=="image/jpeg" || jsonObject["type"].toString()=="image/jpg"){filesuffix=".jpg";}
else if (jsonObject["type"].toString()=="image/png"){filesuffix=".png";}
else {filesuffix="";}
if (helpfilename==""){// check if file has any filename
helpfile=jsonObject["id"].toString();
setFilename(imagedir()+"albums/"+jsonObject["album"].toString()+"/"+jsonObject["id"].toString()+filesuffix);
}
else{setFilename(imagedir()+"albums/"+jsonObject["album"].toString()+"/"+helpfile+filesuffix);}
//qDebug()<<"Filename "<<m_filename;
QFile file(m_filename);
file.open(QIODevice::WriteOnly);
file.write(QByteArray::fromBase64(b64));
buffer.clear();
b64.clear();
file.close();
jsonObject["data"]="";
jsonObject["filename"]=helpfile+filesuffix;
emit this->downloadedjson(m_downloadtype,m_url,m_filename,dlindex,jsonObject);
}
else {
QFile file(m_filename);
file.open(QIODevice::WriteOnly);
file.write(buffer);
buffer.clear();
file.close();
emit this->downloaded(m_downloadtype,m_url,m_filename,dlindex);
//reply->deleteLater();
}
if(downloadtype()=="contactlist" || downloadtype()=="friendrequests" || downloadtype()=="picturelist"){
dlindex=dlindex+1;XHR::getlist();
}
}
void XHR::onReadyRead()
{
qDebug() << ".";
buffer += reply->readAll();
}
//void XHR::updateDownloadProgress(qint64 bytesRead, qint64 totalBytes)
//{
// qDebug() << "Bytes: " << bytesRead<<" / "<<totalBytes;
//}
void XHR::onSSLError(const QList<QSslError> &errors)
{
qDebug() << "XHR::onSSLError :" ;
QListIterator<QSslError> ierrs(errors);
while(ierrs.hasNext()) {
qDebug() << "\t" << ierrs.next().errorString();
}
}
QString XHR::bufferToString()
{
//return QTextCodec::codecForName("utf-8")->toUnicode(buffer);
return QString(buffer);
}

145
src/common/xhr.h Normal file
View file

@ -0,0 +1,145 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef XHR_H
#define XHR_H
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QObject>
#include <QJsonObject>
//#include <QNetworkConfiguration>
class XHR : public QObject
{
Q_OBJECT
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
Q_PROPERTY(QString login READ login WRITE setLogin NOTIFY loginChanged)
Q_PROPERTY(QString token READ token WRITE setToken NOTIFY tokenChanged)
Q_PROPERTY(QVariantMap account READ account WRITE setAccount NOTIFY accountChanged)
Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged)
Q_PROPERTY(QString imagedir READ imagedir WRITE setImagedir NOTIFY imagedirChanged)
Q_PROPERTY(QList<QString> contactlist READ contactlist WRITE setContactlist NOTIFY contactlistChanged)
Q_PROPERTY(QList<QString> filelist READ filelist WRITE setFilelist NOTIFY filelistChanged)
Q_PROPERTY(QString downloadtype READ downloadtype WRITE setDownloadtype NOTIFY downloadtypeChanged)
//Q_PROPERTY(QString networktype READ networktype() NOTIFY networktypeChanged)
public:
static XHR *instance();
explicit XHR(QObject *parent = 0);
QString url() const;
QString api() const;
QString login() const;
QString token() const;
QVariantMap account() const;
QString filename() const;
QList<QString> contactlist() const;
QList<QString> filelist() const;
QString imagedir() const;
QString downloadtype() const;
// QString networktype();
signals:
void urlChanged();
void apiChanged();
void loginChanged();
void tokenChanged();
void accountChanged();
void filenameChanged();
void contactlistChanged();
void filelistChanged();
void imagedirChanged();
void downloadtypeChanged();
void networktypeChanged();
void downloaded(QString type, QString url, QString filename, int i);
void downloadedjson(QString type, QString url, QString filename, int i,QJsonObject jsonObject);
void success(QByteArray data, QString api);
void error(QString data, QString url,QString api, int code);
public slots:
void setUrl(QString url);
void setApi(QString api);
void setLogin(QString login);
void setToken(QString token);
void setAccount(QVariantMap account);
void setDownloadtype(QString downloadtype);
void setFilename(QString filename);
void setContactlist(QList<QString> filename);
void setFilelist(QList<QString> filename);
void setImagedir(QString filename);
void setParam(QString name, QString value);
void setImageFileParam(QString name, QString url);
void clearParams();
void post();
void postJSON();
void get();
void getlist();
void download();
// void networktype();
private slots:
void onReplyError(QNetworkReply::NetworkError code);
void onReplySuccess();
void onRequestFinished();
void onReadyRead();
void onSSLError(const QList<QSslError> &errors);
//void updateDownloadProgress(qint64 bytesRead, qint64 totalBytes);
private:
QByteArray buffer;
QString m_url;
QString m_api;
QString m_login;
QString m_token;
QVariantMap m_account;
QString m_filename;
QString m_downloadtype;
// QString m_networktype;
QHash<QString, QString> params;
QHash<QString, QString> files;
QList<QString> m_filelist;
QList<QString> m_contactlist;
QString m_imagedir;
int dlindex;
QNetworkAccessManager manager;
//QNetworkRequest request;
QNetworkReply *reply;
//QNetworkConfiguration nc;
QString bufferToString();
};
#endif // XHR_H