replace resitation
This commit is contained in:
parent
5344ea0b82
commit
47011429f5
@ -488,6 +488,45 @@ namespace RMuseum.Controllers
|
|||||||
return Ok(res.Result);
|
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>
|
/// <summary>
|
||||||
|
|||||||
@ -3139,6 +3139,19 @@
|
|||||||
<param name="id"></param>
|
<param name="id"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</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)">
|
<member name="M:RMuseum.Controllers.RecitationController.GetUploads(RSecurityBackend.Models.Generic.PagingParameterModel,System.Boolean)">
|
||||||
<summary>
|
<summary>
|
||||||
Get User Uploads
|
Get User Uploads
|
||||||
@ -23481,6 +23494,22 @@
|
|||||||
<param name="userId"></param>
|
<param name="userId"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</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)">
|
<member name="M:RMuseum.Services.Implementationa.RecitationService.GetPoemNarrationVerseSyncArray(System.Int32)">
|
||||||
<summary>
|
<summary>
|
||||||
Gets Verse Sync Range Information
|
Gets Verse Sync Range Information
|
||||||
@ -24064,6 +24093,19 @@
|
|||||||
<param name="userId"></param>
|
<param name="userId"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</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)">
|
<member name="M:RMuseum.Services.IRecitationService.GetPoemNarrationVerseSyncArray(System.Int32)">
|
||||||
<summary>
|
<summary>
|
||||||
Gets Verse Sync Range Information
|
Gets Verse Sync Range Information
|
||||||
|
|||||||
@ -73,6 +73,19 @@ namespace RMuseum.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<RServiceResult<bool>> Delete(int id, Guid userId);
|
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>
|
/// <summary>
|
||||||
/// Gets Verse Sync Range Information
|
/// Gets Verse Sync Range Information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -496,6 +496,161 @@ namespace RMuseum.Services.Implementationa
|
|||||||
return new RServiceResult<bool>(true);
|
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>
|
/// <summary>
|
||||||
/// Gets Verse Sync Range Information
|
/// Gets Verse Sync Range Information
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user