replace resitation
This commit is contained in:
parent
5344ea0b82
commit
47011429f5
@ -488,6 +488,45 @@ namespace RMuseum.Controllers
|
||||
return Ok(res.Result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace the synchronization (xml) file of an already approved recitation belonging to the
|
||||
/// logged on user, without touching its mp3 file. Send the new xml as the single file in the
|
||||
/// request's form-data. The uploaded xml is only accepted if its embedded PoemId and audio
|
||||
/// checksum match the target recitation exactly (i.e. it must be a resync of the very same mp3
|
||||
/// already on record) - this endpoint never accepts a new mp3. On acceptance, the xml is queued
|
||||
/// for re-publishing to the external FTP server(s) in the background and you receive a
|
||||
/// notification with the final result (success or failure).
|
||||
/// </summary>
|
||||
/// <param name="id">recitation id</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("{id}/xml")]
|
||||
[Authorize]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(bool))]
|
||||
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
|
||||
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
|
||||
public async Task<IActionResult> ReplaceRecitationSyncXmlFile(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_audioService.UploadEnabled)
|
||||
return BadRequest("این قابلیت به دلیل تغییرات فنی سایت موقتاً غیرفعال است.");
|
||||
|
||||
Guid loggedOnUserId = new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value);
|
||||
IFormFile xmlFile = Request.Form.Files.FirstOrDefault();
|
||||
RServiceResult<bool> resReplace = await _audioService.ReplaceRecitationSyncXmlFile(loggedOnUserId, id, xmlFile);
|
||||
if (!string.IsNullOrEmpty(resReplace.ExceptionString))
|
||||
{
|
||||
if (resReplace.ExceptionString == "404")
|
||||
return NotFound();
|
||||
return BadRequest(resReplace.ExceptionString);
|
||||
}
|
||||
return Ok(resReplace.Result);
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
return BadRequest(exp.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -3139,6 +3139,19 @@
|
||||
<param name="id"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Controllers.RecitationController.ReplaceRecitationSyncXmlFile(System.Int32)">
|
||||
<summary>
|
||||
Replace the synchronization (xml) file of an already approved recitation belonging to the
|
||||
logged on user, without touching its mp3 file. Send the new xml as the single file in the
|
||||
request's form-data. The uploaded xml is only accepted if its embedded PoemId and audio
|
||||
checksum match the target recitation exactly (i.e. it must be a resync of the very same mp3
|
||||
already on record) - this endpoint never accepts a new mp3. On acceptance, the xml is queued
|
||||
for re-publishing to the external FTP server(s) in the background and you receive a
|
||||
notification with the final result (success or failure).
|
||||
</summary>
|
||||
<param name="id">recitation id</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Controllers.RecitationController.GetUploads(RSecurityBackend.Models.Generic.PagingParameterModel,System.Boolean)">
|
||||
<summary>
|
||||
Get User Uploads
|
||||
@ -23481,6 +23494,22 @@
|
||||
<param name="userId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Services.Implementationa.RecitationService.ReplaceRecitationSyncXmlFile(System.Guid,System.Int32,Microsoft.AspNetCore.Http.IFormFile)">
|
||||
<summary>
|
||||
Replace only the synchronization (xml) file of an existing, approved recitation owned by the user.
|
||||
The recitation's mp3 file is left untouched. The uploaded xml's embedded PoemId and audio file
|
||||
checksum must match the target recitation's GanjoorPostId and Mp3FileCheckSum respectively (i.e.
|
||||
it must be a resync of the very same, already uploaded, mp3 file) or the request is rejected -
|
||||
this method never accepts a new mp3, only a corrected/retimed xml for the existing one.
|
||||
On success the updated xml (and the unchanged mp3) are re-published to the external/backup FTP
|
||||
servers in the background and the user is notified of the final result (success or failure),
|
||||
reusing the exact same publishing/notification pipeline used for normal recitation uploads.
|
||||
</summary>
|
||||
<param name="userId">must be the recitation owner</param>
|
||||
<param name="recitationId"></param>
|
||||
<param name="xmlFile"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Services.Implementationa.RecitationService.GetPoemNarrationVerseSyncArray(System.Int32)">
|
||||
<summary>
|
||||
Gets Verse Sync Range Information
|
||||
@ -24064,6 +24093,19 @@
|
||||
<param name="userId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Services.IRecitationService.ReplaceRecitationSyncXmlFile(System.Guid,System.Int32,Microsoft.AspNetCore.Http.IFormFile)">
|
||||
<summary>
|
||||
Replace only the synchronization (xml) file of an existing, approved recitation owned by the
|
||||
user. The recitation's mp3 file is left untouched; the uploaded xml's embedded PoemId and audio
|
||||
checksum must match the target recitation or the request is rejected. On success, the updated
|
||||
xml is re-published to the external/backup FTP servers in the background and the user is
|
||||
notified of the final result (success or failure).
|
||||
</summary>
|
||||
<param name="userId">must be the recitation owner</param>
|
||||
<param name="recitationId"></param>
|
||||
<param name="xmlFile"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Services.IRecitationService.GetPoemNarrationVerseSyncArray(System.Int32)">
|
||||
<summary>
|
||||
Gets Verse Sync Range Information
|
||||
|
||||
@ -73,6 +73,19 @@ namespace RMuseum.Services
|
||||
/// <returns></returns>
|
||||
Task<RServiceResult<bool>> Delete(int id, Guid userId);
|
||||
|
||||
/// <summary>
|
||||
/// Replace only the synchronization (xml) file of an existing, approved recitation owned by the
|
||||
/// user. The recitation's mp3 file is left untouched; the uploaded xml's embedded PoemId and audio
|
||||
/// checksum must match the target recitation or the request is rejected. On success, the updated
|
||||
/// xml is re-published to the external/backup FTP servers in the background and the user is
|
||||
/// notified of the final result (success or failure).
|
||||
/// </summary>
|
||||
/// <param name="userId">must be the recitation owner</param>
|
||||
/// <param name="recitationId"></param>
|
||||
/// <param name="xmlFile"></param>
|
||||
/// <returns></returns>
|
||||
Task<RServiceResult<bool>> ReplaceRecitationSyncXmlFile(Guid userId, int recitationId, IFormFile xmlFile);
|
||||
|
||||
/// <summary>
|
||||
/// Gets Verse Sync Range Information
|
||||
/// </summary>
|
||||
|
||||
@ -496,6 +496,161 @@ namespace RMuseum.Services.Implementationa
|
||||
return new RServiceResult<bool>(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace only the synchronization (xml) file of an existing, approved recitation owned by the user.
|
||||
/// The recitation's mp3 file is left untouched. The uploaded xml's embedded PoemId and audio file
|
||||
/// checksum must match the target recitation's GanjoorPostId and Mp3FileCheckSum respectively (i.e.
|
||||
/// it must be a resync of the very same, already uploaded, mp3 file) or the request is rejected -
|
||||
/// this method never accepts a new mp3, only a corrected/retimed xml for the existing one.
|
||||
/// On success the updated xml (and the unchanged mp3) are re-published to the external/backup FTP
|
||||
/// servers in the background and the user is notified of the final result (success or failure),
|
||||
/// reusing the exact same publishing/notification pipeline used for normal recitation uploads.
|
||||
/// </summary>
|
||||
/// <param name="userId">must be the recitation owner</param>
|
||||
/// <param name="recitationId"></param>
|
||||
/// <param name="xmlFile"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<RServiceResult<bool>> ReplaceRecitationSyncXmlFile(Guid userId, int recitationId, IFormFile xmlFile)
|
||||
{
|
||||
if (xmlFile == null || xmlFile.Length == 0)
|
||||
{
|
||||
return new RServiceResult<bool>(false, "فایل xml ارسال نشده است.");
|
||||
}
|
||||
if (Path.GetExtension(xmlFile.FileName).ToLower() != ".xml")
|
||||
{
|
||||
return new RServiceResult<bool>(false, "تنها فایل با پسوند xml قابل پذیرش است.");
|
||||
}
|
||||
|
||||
Recitation recitation = await _context.Recitations.Where(r => r.Id == recitationId && r.OwnerId == userId).FirstOrDefaultAsync();
|
||||
if (recitation == null)
|
||||
{
|
||||
return new RServiceResult<bool>(false, "404");
|
||||
}
|
||||
if (recitation.ReviewStatus != AudioReviewStatus.Approved)
|
||||
{
|
||||
await _notificationService.PushNotification
|
||||
(
|
||||
userId,
|
||||
"خطا در جایگزینی فایل xml",
|
||||
$"جایگزینی فایل xml تنها برای خوانشهای تأیید شده امکانپذیر است.{Environment.NewLine}" +
|
||||
$"{recitation.AudioTitle}"
|
||||
, NotificationType.Error
|
||||
);
|
||||
return new RServiceResult<bool>(false, "تنها امکان جایگزینی فایل xml برای خوانشهای تأیید شده وجود دارد.");
|
||||
}
|
||||
|
||||
RServiceResult<UploadSessionFile> savedFile = await SaveUploadedFile(xmlFile);
|
||||
if (!string.IsNullOrEmpty(savedFile.ExceptionString))
|
||||
{
|
||||
return new RServiceResult<bool>(false, savedFile.ExceptionString);
|
||||
}
|
||||
string tempXmlFilePath = savedFile.Result.FilePath;
|
||||
|
||||
List<PoemAudio> parsedAudioList;
|
||||
try
|
||||
{
|
||||
parsedAudioList = PoemAudioListProcessor.Load(tempXmlFilePath);
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
if (File.Exists(tempXmlFilePath))
|
||||
{
|
||||
File.Delete(tempXmlFilePath);
|
||||
}
|
||||
await _notificationService.PushNotification
|
||||
(
|
||||
userId,
|
||||
"خطا در جایگزینی فایل xml",
|
||||
$"خطا در خواندن فایل xml ارسالی برای {recitation.AudioTitle}: {exp.Message}"
|
||||
, NotificationType.Error
|
||||
);
|
||||
return new RServiceResult<bool>(false, $"خطا در خواندن فایل xml: {exp.Message}");
|
||||
}
|
||||
|
||||
PoemAudio audio = parsedAudioList.FirstOrDefault();
|
||||
if (audio == null)
|
||||
{
|
||||
if (File.Exists(tempXmlFilePath))
|
||||
{
|
||||
File.Delete(tempXmlFilePath);
|
||||
}
|
||||
await _notificationService.PushNotification
|
||||
(
|
||||
userId,
|
||||
"خطا در جایگزینی فایل xml",
|
||||
$"فایل xml ارسالی برای {recitation.AudioTitle} اطلاعات معتبری ندارد."
|
||||
, NotificationType.Error
|
||||
);
|
||||
return new RServiceResult<bool>(false, "فایل xml اطلاعات معتبری ندارد.");
|
||||
}
|
||||
|
||||
if (audio.PoemId != recitation.GanjoorPostId)
|
||||
{
|
||||
if (File.Exists(tempXmlFilePath))
|
||||
{
|
||||
File.Delete(tempXmlFilePath);
|
||||
}
|
||||
string msg = $"شناسهٔ شعر درج شده در فایل xml ({audio.PoemId}) با شناسهٔ شعر خوانش انتخابی ({recitation.GanjoorPostId} - {recitation.AudioTitle}) همخوانی ندارد.";
|
||||
await _notificationService.PushNotification
|
||||
(
|
||||
userId,
|
||||
"خطا در جایگزینی فایل xml",
|
||||
msg
|
||||
, NotificationType.Error
|
||||
);
|
||||
return new RServiceResult<bool>(false, msg);
|
||||
}
|
||||
|
||||
if (audio.FileCheckSum != recitation.Mp3FileCheckSum)
|
||||
{
|
||||
if (File.Exists(tempXmlFilePath))
|
||||
{
|
||||
File.Delete(tempXmlFilePath);
|
||||
}
|
||||
string msg = "این فایل xml برای فایل mp3 دیگری همگامسازی شده و با فایل صوتی خوانش انتخابی مطابقت ندارد." +
|
||||
$"{Environment.NewLine}این قابلیت تنها برای جایگزینی فایل xml مربوط به همان فایل mp3 موجود است؛ " +
|
||||
"برای تغییر خود فایل mp3 از روش معمول ارسال خوانش (با گزینهٔ جایگزینی) استفاده کنید.";
|
||||
await _notificationService.PushNotification
|
||||
(
|
||||
userId,
|
||||
"خطا در جایگزینی فایل xml",
|
||||
$"{recitation.AudioTitle}{Environment.NewLine}{msg}"
|
||||
, NotificationType.Error
|
||||
);
|
||||
return new RServiceResult<bool>(false, msg);
|
||||
}
|
||||
|
||||
File.Move(tempXmlFilePath, recitation.LocalXmlFilePath, true);
|
||||
|
||||
recitation.FileLastUpdated = DateTime.Now;
|
||||
recitation.AudioSyncStatus = AudioSyncStatus.SoundOrXMLFilesChanged;
|
||||
_context.Recitations.Update(recitation);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
_backgroundTaskQueue.QueueBackgroundWorkItem
|
||||
(
|
||||
async token =>
|
||||
{
|
||||
using (RMuseumDbContext context = new RMuseumDbContext(new DbContextOptions<RMuseumDbContext>())) //this is long running job, so _context might be already been freed/collected by GC
|
||||
{
|
||||
RecitationPublishingTracker tracker = new RecitationPublishingTracker()
|
||||
{
|
||||
PoemNarrationId = recitation.Id,
|
||||
StartDate = DateTime.Now,
|
||||
XmlFileCopied = false,
|
||||
Mp3FileCopied = false,
|
||||
FirstDbUpdated = false,
|
||||
SecondDbUpdated = false,
|
||||
};
|
||||
context.RecitationPublishingTrackers.Add(tracker);
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
await _PublishNarration(recitation, tracker, context);
|
||||
}
|
||||
});
|
||||
|
||||
return new RServiceResult<bool>(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets Verse Sync Range Information
|
||||
|
||||
Loading…
Reference in New Issue
Block a user