Skip to content

Commit

Permalink
src/anki/ankiclient: send files using base64 over json
Browse files Browse the repository at this point in the history
Use base64 encoding to send files to Anki. This has the benefit of
bypassing filesystem restrictions when using local files. It comes at
the cost of sending 33% more data. For the small file sizes being delt
with, this is unimportant. This also fixes the rare case where the
AnkiConnect server is on a different computer than Memento.

Closes #189
  • Loading branch information
ripose-jp committed Dec 29, 2023
1 parent a3b45f0 commit 8c0af66
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 16 deletions.
35 changes: 22 additions & 13 deletions src/anki/ankiclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
#define ANKI_NOTE_TAGS "tags"
#define ANKI_NOTE_AUDIO "audio"
#define ANKI_NOTE_PICTURE "picture"
#define ANKI_NOTE_DATA "data"
#define ANKI_NOTE_URL "url"
#define ANKI_NOTE_PATH "path"
#define ANKI_NOTE_FILENAME "filename"
Expand Down Expand Up @@ -144,10 +145,6 @@ AnkiClient::AnkiClient(QObject *parent) : QObject(parent)

AnkiClient::~AnkiClient()
{
for (const QString &path : m_tempFiles)
{
QFile(path).remove();
}
delete m_manager;
}

Expand Down Expand Up @@ -823,7 +820,7 @@ AnkiReply *AnkiClient::addMedia(const QList<QPair<QString, QString>> &fileMap)
QJsonObject command;
command[ANKI_ACTION] = ANKI_ACTION_STORE_MEDIA_FILE;
QJsonObject fileParams;
fileParams[ANKI_NOTE_PATH] = p.first;
fileParams[ANKI_NOTE_DATA] = fileToBase64(p.first);
fileParams[ANKI_NOTE_FILENAME] = p.second;
command[ANKI_PARAMS] = fileParams;

Expand Down Expand Up @@ -1424,12 +1421,13 @@ void AnkiClient::buildCommonNote(
);
}
if (!path.isEmpty()) {
audObj[ANKI_NOTE_PATH] = path;
m_tempFiles.append(path);
audObj[ANKI_NOTE_DATA] = fileToBase64(path);
QString filename = FileUtils::calculateMd5(path) + ".aac";
audObj[ANKI_NOTE_FILENAME] = filename;
audObj[ANKI_NOTE_FIELDS] = fieldsWithAudioMedia;
audio.append(audObj);

QFile(path).remove();
}
}

Expand All @@ -1454,12 +1452,13 @@ void AnkiClient::buildCommonNote(
);
}
if (!path.isEmpty()) {
audObj[ANKI_NOTE_PATH] = path;
m_tempFiles.append(path);
audObj[ANKI_NOTE_DATA] = fileToBase64(path);
QString filename = FileUtils::calculateMd5(path) + ".aac";
audObj[ANKI_NOTE_FILENAME] = filename;
audObj[ANKI_NOTE_FIELDS] = fieldsWithAudioContext;
audio.append(audObj);

QFile(path).remove();
}
}

Expand Down Expand Up @@ -1494,8 +1493,7 @@ void AnkiClient::buildCommonNote(
const bool visibility = player->getSubVisibility();
player->setSubVisiblity(true);
QString path = player->tempScreenshot(true, imageExt);
image[ANKI_NOTE_PATH] = path;
m_tempFiles.append(path);
image[ANKI_NOTE_DATA] = fileToBase64(path);
player->setSubVisiblity(visibility);

QString filename = FileUtils::calculateMd5(path) + imageExt;
Expand All @@ -1507,15 +1505,15 @@ void AnkiClient::buildCommonNote(
{
images.append(image);
}
QFile(path).remove();
}

if (!fieldWithScreenshotVideo.isEmpty())
{
QJsonObject image;
QString path = GlobalMediator::getGlobalMediator()
->getPlayerAdapter()->tempScreenshot(false, imageExt);
image[ANKI_NOTE_PATH] = path;
m_tempFiles.append(path);
image[ANKI_NOTE_DATA] = fileToBase64(path);

QString filename = FileUtils::calculateMd5(path) + imageExt;
image[ANKI_NOTE_FILENAME] = filename;
Expand All @@ -1526,6 +1524,7 @@ void AnkiClient::buildCommonNote(
{
images.append(image);
}
QFile(path).remove();
}

if (!images.isEmpty())
Expand Down Expand Up @@ -1795,4 +1794,14 @@ QString &AnkiClient::accumulateTags(const QList<Tag> &tags, QString &tagStr)
return tagStr;
}

QString AnkiClient::fileToBase64(const QString &path)
{
QFile file(path);
if (!file.open(QIODevice::ReadOnly))
{
return {};
}
return file.readAll().toBase64();
}

/* End Note Helpers */
10 changes: 7 additions & 3 deletions src/anki/ankiclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,13 @@ private Q_SLOTS:
*/
QString &accumulateTags(const QList<Tag> &tags, QString &tagStr);

/**
* Helper method to convert file to base64.
* @param path The path of the file to convert to base64.
* @return The base64 encoded file.
*/
static QString fileToBase64(const QString &path);

/* true if a config exists, false otherwise */
bool m_configExists = false;

Expand All @@ -511,9 +518,6 @@ private Q_SLOTS:

/* The Network Manager for this object. */
QNetworkAccessManager *m_manager;

/* List of temp files to clean up */
QList<QString> m_tempFiles;
};

#endif // ANKICLIENT_H

0 comments on commit 8c0af66

Please sign in to comment.