File indexing completed on 2024-05-12 04:45:59

0001 
0002 /*
0003  * Copyright 2019  Linus Jahn <lnj@kaidan.im>
0004  *
0005  * This program is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU General Public License as
0007  * published by the Free Software Foundation; either version 2 of
0008  * the License or (at your option) version 3 or any later version
0009  * accepted by the membership of KDE e.V. (or its successor approved
0010  * by the membership of KDE e.V.), which shall act as a proxy
0011  * defined in Section 14 of version 3 of the license.
0012  *
0013  * This program is distributed in the hope that it will be useful,
0014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0016  * GNU General Public License for more details.
0017  *
0018  * You should have received a copy of the GNU General Public License
0019  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0020  */
0021 #include "linuxinterface.h"
0022 
0023 #include <KContacts/Addressee>
0024 #include <KContacts/VCardConverter>
0025 #include <KPeople/KPeople/PersonsModel>
0026 #include <KPeople/KPeopleBackend/AbstractContact>
0027 #include <KPeople/PersonData>
0028 #include <QCryptographicHash>
0029 #include <QDebug>
0030 #include <QDirIterator>
0031 #include <QFile>
0032 #include <QStandardPaths>
0033 #include <algorithm>
0034 
0035 using namespace KContacts;
0036 LinuxInterface::LinuxInterface(QObject *parent)
0037     : AbstractInterface(parent)
0038 {
0039 }
0040 
0041 static FMH::MODEL vCardData(const QString &url)
0042 {
0043     FMH::MODEL res;
0044     QFile file(url);
0045     if (!(file.exists())) {
0046         qWarning() << "Can't read vcard, file doesn't exist";
0047         return res;
0048     }
0049 
0050     if (!file.open(QIODevice::ReadOnly)) {
0051         qWarning() << "Couldn't update vCard: Couldn't open file for reading / writing.";
0052         return res;
0053     }
0054 
0055     VCardConverter converter;
0056 
0057     Addressee adr = converter.parseVCard(file.readAll());
0058 
0059     qDebug() << adr.url().toString() << adr.customs() << adr.formattedName() << adr.fullEmail();
0060     res = {//        {FMH::MODEL_KEY::ID, QStringLiteral("vcard:/")+url},
0061            //            {FMH::MODEL_KEY::N, adr.name()},
0062            {FMH::MODEL_KEY::ORG, adr.organization()},
0063            {FMH::MODEL_KEY::GENDER, adr.gender().gender()},
0064            {FMH::MODEL_KEY::TITLE, adr.title()},
0065            {FMH::MODEL_KEY::NOTE, adr.note()},
0066            {FMH::MODEL_KEY::URL, adr.url().toString()},
0067            {FMH::MODEL_KEY::FAV, adr.custom("fav", "fav")},
0068            //            {FMH::MODEL_KEY::EMAIL, adr.emails().join(",")},
0069            //            {FMH::MODEL_KEY::TEL, [phones = adr.phoneNumbers(PhoneNumber::Cell)]()
0070            //             {
0071            //                 return std::accumulate(phones.begin(), phones.end(), QStringList(), [](QStringList &value, const PhoneNumber &number) -> QStringList
0072            //                 {
0073            //                     return value << number.number();
0074            //                 });
0075            //             }().join(",")
0076            //            },
0077            {FMH::MODEL_KEY::PHOTO, adr.photo().url()}};
0078 
0079     file.close();
0080     return res;
0081 }
0082 
0083 void LinuxInterface::getContacts()
0084 {
0085     //    QDirIterator it(this->path, {"*.vcf"}, QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
0086 
0087     //    while(it.hasNext())
0088     //        this->m_contacts <<
0089 
0090     KPeople::PersonsModel model;
0091     for (auto i = 0; i < model.rowCount(); i++) {
0092         const auto uri = model.get(i, KPeople::PersonsModel::PersonUriRole).toString();
0093 
0094         KPeople::PersonData person(uri);
0095         QMultiHash contact = FMH::MODEL {
0096             {FMH::MODEL_KEY::ID, person.personUri()}, {FMH::MODEL_KEY::N, person.name()}, {FMH::MODEL_KEY::EMAIL, person.email()}, {FMH::MODEL_KEY::TEL, person.contactCustomProperty("phoneNumber").toString()},
0097             //        {FMH::MODEL_KEY::PHOTO, person.pictureUrl().toString()}
0098         };
0099         this->m_contacts << contact.unite(vCardData(QString(uri).replace("vcard:/", "")));
0100     }
0101 
0102     emit this->contactsReady(this->m_contacts);
0103 }
0104 
0105 FMH::MODEL LinuxInterface::getContact(const QString &id)
0106 {
0107     FMH::MODEL res;
0108     auto personUri = id;
0109 
0110     if (!(QUrl(personUri).scheme() == "vcard")) {
0111         qWarning() << "uri of contact is not a vcard, cannot get contact.";
0112         return res;
0113     }
0114     return vCardData(personUri.remove("vcard:/"));
0115 }
0116 
0117 bool LinuxInterface::insertContact(const FMH::MODEL &contact)
0118 {
0119     qDebug() << "TRYIN TO INSERT VACRD CONTACT" << contact;
0120     // addresses
0121     Addressee adr;
0122     adr.setName(contact[FMH::MODEL_KEY::N]);
0123     //    adr.setUid(contact[FMH::MODEL_KEY::ID]);
0124     adr.setUrl(contact[FMH::MODEL_KEY::URL]);
0125     adr.setNote(contact[FMH::MODEL_KEY::NOTE]);
0126     adr.setTitle(contact[FMH::MODEL_KEY::TITLE]);
0127     adr.setOrganization(contact[FMH::MODEL_KEY::ORG]);
0128     adr.setGender(contact[FMH::MODEL_KEY::GENDER]);
0129 
0130     adr.setCustoms({QString("%1:%2").arg(FMH::MODEL_NAME[FMH::MODEL_KEY::FAV], contact[FMH::MODEL_KEY::FAV])});
0131 
0132     Email email;
0133     email.setEmail(contact[FMH::MODEL_KEY::EMAIL]);
0134     adr.setEmailList({email});
0135 
0136     Picture photo;
0137     photo.setUrl(contact[FMH::MODEL_KEY::PHOTO]);
0138     adr.setPhoto(photo);
0139 
0140     PhoneNumber phoneNum;
0141     phoneNum.setNumber(contact[FMH::MODEL_KEY::TEL]);
0142     phoneNum.setType(PhoneNumber::Cell);
0143     adr.setPhoneNumbers({phoneNum});
0144 
0145     // create vcard
0146     VCardConverter converter;
0147     QByteArray vcard = converter.createVCard(adr);
0148     qDebug() << vcard;
0149 
0150     // save vcard
0151     QCryptographicHash hash(QCryptographicHash::Sha1);
0152     hash.addData(adr.name().toUtf8());
0153     QFile file(this->path + "/" + hash.result().toHex() + ".vcf");
0154 
0155     if (!file.open(QFile::WriteOnly)) {
0156         qWarning() << "Couldn't save vCard: Couldn't open file for writing.";
0157         return false;
0158     }
0159 
0160     file.write(vcard.data(), vcard.length());
0161     file.close();
0162 
0163     return true;
0164 }
0165 
0166 bool LinuxInterface::updateContact(const QString &id, const FMH::MODEL &contact)
0167 {
0168     auto personUri = id;
0169 
0170     if (!(QUrl(personUri).scheme() == "vcard")) {
0171         qWarning() << "uri of contact to update is not a vcard, cannot update.";
0172         return false;
0173     }
0174 
0175     QFile file(personUri.remove("vcard:/"));
0176     if (!(file.exists())) {
0177         qWarning() << "Can't read vcard, file doesn't exist";
0178         return false;
0179     }
0180     if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
0181         qWarning() << "Couldn't update vCard: Couldn't open file for reading / writing.";
0182         return false;
0183     }
0184 
0185     VCardConverter converter;
0186     Addressee adr = converter.parseVCard(file.readAll());
0187 
0188     for (const auto &key : contact.keys()) {
0189         const auto data = contact[key];
0190         qDebug() << "updating filed:" << key << data;
0191         switch (key) {
0192         case FMH::MODEL_KEY::N: {
0193             if (!data.isEmpty())
0194                 adr.setName(data);
0195             break;
0196         }
0197 
0198         case FMH::MODEL_KEY::TEL: {
0199             PhoneNumber::List phoneNums;
0200             PhoneNumber phoneNum;
0201             phoneNum.setNumber(data);
0202             phoneNum.setType(PhoneNumber::Cell);
0203             phoneNums.append(phoneNum);
0204             adr.setPhoneNumbers(phoneNums);
0205             break;
0206         }
0207 
0208         case FMH::MODEL_KEY::ORG: {
0209             adr.setOrganization(data);
0210             break;
0211         }
0212 
0213         case FMH::MODEL_KEY::TITLE: {
0214             adr.setTitle(data);
0215             break;
0216         }
0217 
0218         case FMH::MODEL_KEY::FAV: {
0219             adr.setCustoms({QString("%1:%2").arg(FMH::MODEL_NAME[FMH::MODEL_KEY::FAV], data)});
0220             break;
0221         }
0222 
0223         case FMH::MODEL_KEY::EMAIL: {
0224             Email email;
0225             email.setEmail(data);
0226             adr.setEmailList({email});
0227             break;
0228         }
0229 
0230         case FMH::MODEL_KEY::NOTE: {
0231             adr.setNote(data);
0232             break;
0233         }
0234 
0235         case FMH::MODEL_KEY::GENDER: {
0236             adr.setGender(data);
0237             break;
0238         }
0239 
0240         case FMH::MODEL_KEY::PHOTO: {
0241             Picture photo;
0242             photo.setUrl(data);
0243             adr.setPhoto(photo);
0244             break;
0245         }
0246 
0247         case FMH::MODEL_KEY::URL: {
0248             adr.setUrl(data);
0249             break;
0250         }
0251 
0252         default:
0253             break;
0254         }
0255     }
0256 
0257     QByteArray vcard = converter.createVCard(adr);
0258     qDebug() << vcard;
0259 
0260     file.write(vcard);
0261     file.close();
0262     return true;
0263 }
0264 
0265 bool LinuxInterface::removeContact(const QString &id)
0266 {
0267     if (!(QUrl(id).scheme() == "vcard")) {
0268         qWarning() << "uri of contact to remove is not a vcard, cannot remove.";
0269         return false;
0270     }
0271 
0272     return QFile::remove(QString(id).remove("vcard:/"));
0273 }
0274 
0275 QImage LinuxInterface::contactPhoto(const QString &id)
0276 {
0277     auto personUri = id;
0278 
0279     if (!(QUrl(personUri).scheme() == "vcard")) {
0280         qWarning() << "uri of contact is not a vcard, cannot get photo.";
0281         return QImage();
0282     }
0283 
0284     QFileInfo file(personUri.remove("vcard:/"));
0285     if (!(file.exists())) {
0286         qWarning() << "Can't read vcard, file doesn't exist";
0287         return QImage();
0288     }
0289 
0290     qDebug() << "IMAGE FILE REQUESTED" << vCardData(personUri)[FMH::MODEL_KEY::PHOTO];
0291     return QImage(vCardData(personUri)[FMH::MODEL_KEY::PHOTO].replace("file://", ""));
0292 }