Name files by index, not by media date.

This commit is contained in:
John Preston 2018-06-20 21:32:52 +01:00
parent 0a5eac50be
commit a253d34c00
3 changed files with 84 additions and 64 deletions

View File

@ -27,12 +27,6 @@ constexpr auto kChatPeerIdShift = (2ULL << 32);
} // namespace
QString PreparePhotoFileName(TimeId date) {
return "Photo_"
+ QString::fromUtf8(FormatDateTime(date, '_', '_', '_'))
+ ".jpg";
}
PeerId UserPeerId(int32 userId) {
return kUserPeerIdShift | uint32(userId);
}
@ -178,7 +172,9 @@ void ParseAttributes(
}
}
QString ComputeDocumentName(const Document &data, TimeId date) {
QString ComputeDocumentName(
ParseMediaContext &context,
const Document &data) {
if (!data.name.isEmpty()) {
return QString::fromUtf8(data.name);
}
@ -188,27 +184,27 @@ QString ComputeDocumentName(const Document &data, TimeId date) {
return !mimeString.compare(mime, Qt::CaseInsensitive);
};
const auto patterns = mimeType.globPatterns();
auto pattern = patterns.isEmpty() ? QString() : patterns.front();
auto extension = QString();
auto prefix = QString();
const auto pattern = patterns.isEmpty() ? QString() : patterns.front();
if (data.isVoiceMessage) {
const auto isMP3 = hasMimeType(qstr("audio/mp3"));
extension = isMP3 ? qsl(".mp3") : qsl(".ogg");
prefix = qsl("Audio_");
return qsl("Audio_")
+ QString::number(++context.audios)
+ (isMP3 ? qsl(".mp3") : qsl(".ogg"));
} else if (data.isVideoFile) {
extension = pattern.isEmpty()
const auto extension = pattern.isEmpty()
? qsl(".mov")
: QString(pattern).replace('*', QString());
prefix = qsl("Video_");
return qsl("Video_")
+ QString::number(++context.videos)
+ extension;
} else {
extension = pattern.isEmpty()
const auto extension = pattern.isEmpty()
? qsl(".unknown")
: pattern.replace('*', QString());
prefix = qsl("File_");
: QString(pattern).replace('*', QString());
return qsl("File_")
+ QString::number(++context.files)
+ extension;
}
return prefix
+ QString::fromUtf8(FormatDateTime(date, '_', '_', '_'))
+ extension;
}
QString CleanDocumentName(QString name) {
@ -274,9 +270,9 @@ QString DocumentFolder(const Document &data) {
}
Document ParseDocument(
ParseMediaContext &context,
const MTPDocument &data,
const QString &suggestedFolder,
TimeId date) {
const QString &suggestedFolder) {
auto result = Document();
data.match([&](const MTPDdocument &data) {
result.id = data.vid.v;
@ -291,8 +287,7 @@ Document ParseDocument(
ParseAttributes(result, data.vattributes);
result.file.suggestedPath = suggestedFolder
+ DocumentFolder(result) + '/'
+ CleanDocumentName(
ComputeDocumentName(result, date ? date : result.date));
+ CleanDocumentName(ComputeDocumentName(context, result));
}, [&](const MTPDdocumentEmpty &data) {
result.id = data.vid.v;
});
@ -341,15 +336,15 @@ Invoice ParseInvoice(const MTPDmessageMediaInvoice &data) {
return result;
}
UserpicsSlice ParseUserpicsSlice(const MTPVector<MTPPhoto> &data) {
UserpicsSlice ParseUserpicsSlice(
const MTPVector<MTPPhoto> &data,
int baseIndex) {
const auto &list = data.v;
auto result = UserpicsSlice();
result.list.reserve(list.size());
for (const auto &photo : list) {
const auto suggestedPath = "PersonalPhotos/"
+ (photo.type() == mtpc_photo
? PreparePhotoFileName(photo.c_photo().vdate.v)
: "Photo_Empty.jpg");
"Photo_" + QString::number(++baseIndex) + ".jpg";
result.list.push_back(ParsePhoto(photo, suggestedPath));
}
return result;
@ -565,10 +560,9 @@ const File &Media::file() const {
}
Media ParseMedia(
ParseMediaContext &context,
const MTPMessageMedia &data,
const QString &folder,
TimeId date,
int32 botId) {
const QString &folder) {
Expects(folder.isEmpty() || folder.endsWith(QChar('/')));
auto result = Media();
@ -576,7 +570,8 @@ Media ParseMedia(
result.content = data.has_photo()
? ParsePhoto(
data.vphoto,
folder + "Photos/" + PreparePhotoFileName(date))
folder + "Photos/"
"Photo_" + QString::number(++context.photos) + ".jpg")
: Photo();
if (data.has_ttl_seconds()) {
result.ttl = data.vttl_seconds.v;
@ -589,7 +584,7 @@ Media ParseMedia(
result.content = UnsupportedMedia();
}, [&](const MTPDmessageMediaDocument &data) {
result.content = data.has_document()
? ParseDocument(data.vdocument, folder, date)
? ParseDocument(context, data.vdocument, folder)
: Document();
if (data.has_ttl_seconds()) {
result.ttl = data.vttl_seconds.v;
@ -599,7 +594,7 @@ Media ParseMedia(
}, [&](const MTPDmessageMediaVenue &data) {
result.content = ParseVenue(data);
}, [&](const MTPDmessageMediaGame &data) {
result.content = ParseGame(data.vgame, botId);
result.content = ParseGame(data.vgame, context.botId);
}, [&](const MTPDmessageMediaInvoice &data) {
result.content = ParseInvoice(data);
}, [&](const MTPDmessageMediaGeoLive &data) {
@ -610,9 +605,9 @@ Media ParseMedia(
}
ServiceAction ParseServiceAction(
ParseMediaContext &context,
const MTPMessageAction &data,
const QString &mediaFolder,
TimeId date) {
const QString &mediaFolder) {
auto result = ServiceAction();
data.match([&](const MTPDmessageActionChatCreate &data) {
auto content = ActionChatCreate();
@ -630,7 +625,8 @@ ServiceAction ParseServiceAction(
auto content = ActionChatEditPhoto();
content.photo = ParsePhoto(
data.vphoto,
mediaFolder + "Photos/" + PreparePhotoFileName(date));
mediaFolder + "Photos/"
"Photo_" + QString::number(++context.photos) + ".jpg");
result.content = content;
}, [&](const MTPDmessageActionChatDeletePhoto &data) {
result.content = ActionChatDeletePhoto();
@ -764,7 +760,10 @@ const File &Message::file() const {
return media.file();
}
Message ParseMessage(const MTPMessage &data, const QString &mediaFolder) {
Message ParseMessage(
ParseMediaContext &context,
const MTPMessage &data,
const QString &mediaFolder) {
auto result = Message();
data.match([&](const MTPDmessage &data) {
result.id = data.vid.v;
@ -772,7 +771,7 @@ Message ParseMessage(const MTPMessage &data, const QString &mediaFolder) {
if (IsChatPeerId(peerId)) {
result.chatId = BarePeerId(peerId);
}
const auto date = result.date = data.vdate.v;
result.date = data.vdate.v;
if (data.has_edit_date()) {
result.edited = data.vedit_date.v;
}
@ -802,15 +801,16 @@ Message ParseMessage(const MTPMessage &data, const QString &mediaFolder) {
result.viaBotId = data.vvia_bot_id.v;
}
if (data.has_media()) {
context.botId = (result.viaBotId
? result.viaBotId
: result.forwardedFromId
? result.forwardedFromId
: result.fromId);
result.media = ParseMedia(
context,
data.vmedia,
mediaFolder,
date,
(result.viaBotId
? result.viaBotId
: result.forwardedFromId
? result.forwardedFromId
: result.fromId));
mediaFolder);
context.botId = 0;
}
result.text = ParseString(data.vmessage);
}, [&](const MTPDmessageService &data) {
@ -819,8 +819,11 @@ Message ParseMessage(const MTPMessage &data, const QString &mediaFolder) {
if (IsChatPeerId(peerId)) {
result.chatId = BarePeerId(peerId);
}
const auto date = result.date = data.vdate.v;
result.action = ParseServiceAction(data.vaction, mediaFolder, date);
result.date = data.vdate.v;
result.action = ParseServiceAction(
context,
data.vaction,
mediaFolder);
if (data.has_from_id()) {
result.fromId = data.vfrom_id.v;
}
@ -836,9 +839,10 @@ Message ParseMessage(const MTPMessage &data, const QString &mediaFolder) {
std::map<uint64, Message> ParseMessagesList(
const MTPVector<MTPMessage> &data,
const QString &mediaFolder) {
auto context = ParseMediaContext();
auto result = std::map<uint64, Message>();
for (const auto &message : data.v) {
auto parsed = ParseMessage(message, mediaFolder);
auto parsed = ParseMessage(context, message, mediaFolder);
const auto shift = uint64(uint32(parsed.chatId)) << 32;
result.emplace(shift | uint32(parsed.id), std::move(parsed));
}
@ -1097,6 +1101,7 @@ void FinalizeLeftChannelsInfo(DialogsInfo &info, const Settings &settings) {
}
MessagesSlice ParseMessagesSlice(
ParseMediaContext &context,
const MTPVector<MTPMessage> &data,
const MTPVector<MTPUser> &users,
const MTPVector<MTPChat> &chats,
@ -1104,10 +1109,10 @@ MessagesSlice ParseMessagesSlice(
const auto &list = data.v;
auto result = MessagesSlice();
result.list.reserve(list.size());
for (const auto &message : list) {
result.list.push_back(ParseMessage(message, mediaFolder));
for (auto i = list.size(); i != 0;) {
const auto &message = list[--i];
result.list.push_back(ParseMessage(context, message, mediaFolder));
}
ranges::reverse(result.list);
result.peers = ParsePeersLists(users, chats);
return result;
}

View File

@ -142,7 +142,9 @@ struct UserpicsSlice {
std::vector<Photo> list;
};
UserpicsSlice ParseUserpicsSlice(const MTPVector<MTPPhoto> &data);
UserpicsSlice ParseUserpicsSlice(
const MTPVector<MTPPhoto> &data,
int baseIndex);
struct ContactInfo {
int32 userId = 0;
@ -259,10 +261,18 @@ struct Media {
const File &file() const;
};
struct ParseMediaContext {
int photos = 0;
int audios = 0;
int videos = 0;
int files = 0;
int32 botId = 0;
};
Media ParseMedia(
ParseMediaContext &context,
const MTPMessageMedia &data,
const QString &folder,
TimeId date);
const QString &folder);
struct ActionChatCreate {
Utf8String title;
@ -387,9 +397,9 @@ struct ServiceAction {
};
ServiceAction ParseServiceAction(
ParseMediaContext &context,
const MTPMessageAction &data,
const QString &mediaFolder,
TimeId date);
const QString &mediaFolder);
struct Message {
int32 id = 0;
@ -409,7 +419,10 @@ struct Message {
const File &file() const;
};
Message ParseMessage(const MTPMessage &data, const QString &mediaFolder);
Message ParseMessage(
ParseMediaContext &context,
const MTPMessage &data,
const QString &mediaFolder);
std::map<uint64, Message> ParseMessagesList(
const MTPVector<MTPMessage> &data,
const QString &mediaFolder);
@ -458,6 +471,7 @@ struct MessagesSlice {
};
MessagesSlice ParseMessagesSlice(
ParseMediaContext &context,
const MTPVector<MTPMessage> &data,
const MTPVector<MTPUser> &users,
const MTPVector<MTPChat> &chats,

View File

@ -128,6 +128,7 @@ struct ApiWrap::UserpicsProcess {
Fn<bool(Data::UserpicsSlice&&)> handleSlice;
FnMut<void()> finish;
int processed = 0;
base::optional<Data::UserpicsSlice> slice;
uint64 maxId = 0;
bool lastSlice = false;
@ -191,6 +192,7 @@ struct ApiWrap::ChatProcess {
int32 offsetId = 1;
Data::ParseMediaContext context;
base::optional<Data::MessagesSlice> slice;
bool lastSlice = false;
int fileIndex = -1;
@ -513,7 +515,9 @@ void ApiWrap::handleUserpicsSlice(const MTPphotos_Photos &result) {
if constexpr (MTPDphotos_photos::Is<decltype(data)>()) {
_userpicsProcess->lastSlice = true;
}
loadUserpicsFiles(Data::ParseUserpicsSlice(data.vphotos));
loadUserpicsFiles(Data::ParseUserpicsSlice(
data.vphotos,
_userpicsProcess->processed));
});
}
@ -556,6 +560,7 @@ void ApiWrap::finishUserpicsSlice() {
auto slice = *base::take(_userpicsProcess->slice);
if (!slice.list.empty()) {
_userpicsProcess->processed += slice.list.size();
_userpicsProcess->maxId = slice.list.back().id;
if (!_userpicsProcess->handleSlice(std::move(slice))) {
return;
@ -702,7 +707,6 @@ void ApiWrap::requestMessages(
void ApiWrap::requestDialogsSlice() {
Expects(_dialogsProcess != nullptr);
LOG(("REQUEST %1 %2").arg(_dialogsProcess->offsetDate).arg(_dialogsProcess->offsetId));
mainRequest(MTPmessages_GetDialogs(
MTP_flags(0),
MTP_int(_dialogsProcess->offsetDate),
@ -726,10 +730,6 @@ void ApiWrap::requestDialogsSlice() {
_dialogsProcess->offsetDate = last.topMessageDate;
_dialogsProcess->offsetPeer = last.input;
for (const auto &item : info.list) {
LOG(("RESULT: %1 %2").arg(item.topMessageDate).arg(item.topMessageId));
}
appendDialogsSlice(std::move(info));
const auto count = _dialogsProcess->info.list.size();
@ -856,6 +856,7 @@ void ApiWrap::requestMessagesSlice(FnMut<bool(int count)> start) {
_chatProcess->lastSlice = true;
}
loadMessagesFiles(Data::ParseMessagesSlice(
_chatProcess->context,
data.vmessages,
data.vusers,
data.vchats,