Backend for the Teso project written in 2022
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

688 lines
31 KiB

3 months ago
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using FFMpegCore;
using FFMpegCore.Enums;
using Google.Apis.Auth.OAuth2;
using Google.Cloud.Firestore;
using Grpc.Auth;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
using Teso_API.Models;
namespace Teso_API.Controllers
{
[AllowAnonymous, Route("posts")]
[ApiController]
public class PostsController : ControllerBase
{
private readonly TESOContext _context;
private FirestoreDb db;
public PostsController(TESOContext context)
{
_context = context;
db = new FirestoreDbBuilder
{
ProjectId = ServerLocation.credentials.project_id,
ChannelCredentials = GoogleCredential.FromJson(JsonConvert.SerializeObject(ServerLocation.credentials)).ToChannelCredentials(),
}.Build();
}
[Authorize]
[Route("mypost"), HttpGet]
public async Task<ActionResult<IEnumerable<PostedAd>>> GetPosts()
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
List<PostedAd> postedAds = new List<PostedAd>();
List<Post> posts = await _context.Posts.AsQueryable().Where(i => i.PublisherId == userID).OrderByDescending(t => t.Timestamp).ToListAsync();
foreach (Post post in posts)
{
PostedAd upload = new PostedAd();
upload.post = post;
upload.likes = await _context.PostFavs.AsQueryable().Where(l => l.PostId == post.PostId).ToListAsync();
upload.comments = await _context.CommentsPosts.AsQueryable().Where(c => c.PostId == post.PostId).ToListAsync();
upload.campaignAd = await _context.CampAds.AsQueryable().AnyAsync(p => p.PostId == post.PostId);
if (upload.campaignAd)
{
upload.campaignAdvert = await _context.CampAds.AsQueryable().Where(d => d.PostId == post.PostId).AsNoTracking().FirstAsync();
if (upload.campaignAdvert != null)
{
postedAds.Add(upload);
}
}
else
{
postedAds.Add(upload);
}
}
return postedAds;
}
[Authorize]
[Route("userpost"), HttpPost]
public async Task<ActionResult<IEnumerable<PostedAd>>> UserPost([FromBody] string id)
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
List<PostedAd> postedAds = new List<PostedAd>();
List<Post> posts = await _context.Posts.AsQueryable().Where(i => i.PublisherId == id)
.Select(e => new Post
{
Aspect = e.Aspect,
PlaybackID = e.PlaybackID,
PostId = e.PostId,
PublisherId = e.PublisherId,
AssetID = e.AssetID,
Timestamp = e.Timestamp,
Title = e.Title,
Rendition = e.Rendition,
})
.OrderByDescending(t => t.Timestamp).ToListAsync();
foreach (Post post in posts)
{
if (!_context.ReportedContents.Any(p => p.PostId == post.PostId && p.UserGuid == userID))
{
PostedAd upload = new PostedAd();
upload.post = post;
upload.likes = await _context.PostFavs.AsQueryable().Where(l => l.PostId == post.PostId).ToListAsync();
upload.comments = await _context.CommentsPosts.AsQueryable().Where(c => c.PostId == post.PostId).ToListAsync();
upload.campaignAd = await _context.CampAds.AsQueryable().AnyAsync(p => p.PostId == post.PostId);
if (upload.campaignAd)
{
upload.campaignAdvert = await _context.CampAds.AsQueryable().Where(d => d.PostId == post.PostId).AsNoTracking().FirstAsync();
if (upload.campaignAdvert != null && upload.campaignAdvert.Approved.Value)
{
postedAds.Add(upload);
}
}
else
{
postedAds.Add(upload);
}
}
}
return postedAds;
}
[Authorize]
[Route("homefeed"), HttpPost]
public async Task<ActionResult<IEnumerable<Post>>> HomeFeed()
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
var param = new SqlParameter[]
{
new SqlParameter
{
ParameterName = "@user",
SqlValue = userID,
SqlDbType = System.Data.SqlDbType.VarChar,
Direction = System.Data.ParameterDirection.Input
},
new SqlParameter
{
ParameterName = "@status",
SqlValue = 0,
SqlDbType = System.Data.SqlDbType.Bit,
Direction = System.Data.ParameterDirection.Input
},
};
List<Post> posts = await _context.Posts.FromSqlRaw("exec dbo.[usp_posts_get] @user,@status", param).ToListAsync();
return posts;
}
[Authorize]
[Route("upload-post"), HttpPost]
public async Task<ActionResult> UploadPost(PostUpload post)
{
try
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
Post newPost = new Post();
newPost.PlaybackID = post.path;
newPost.Title = post.title;
newPost.Timestamp = DateTime.Now;
newPost.PublisherId = userID;
newPost.PostId = "TESADS" + String.Format("{0:d6}", (DateTime.Now.Ticks / 10) % 100000);
newPost.AssetID = post.thumbnail;
newPost.Aspect = post.aspect;
WriteBatch batch = db.StartBatch();
if (!String.IsNullOrEmpty(post.campaignID))
{
CampAd campaignAdvert = new CampAd();
campaignAdvert.PostId = newPost.PostId;
campaignAdvert.CampaignId = post.campaignID;
campaignAdvert.Approved = null;
string businessID = await _context.Campaigns.AsQueryable().Where(bid => bid.CampaignId == campaignAdvert.CampaignId)
.Select(b => b.BusinessId).FirstOrDefaultAsync();
TesoBusinessDetail recipient = await _context.TesoBusinessDetails.AsQueryable().Where(i => i.BusinessId == businessID).FirstOrDefaultAsync();
TesoUserDetail requester = await _context.TesoUserDetails.AsQueryable().Where(i => i.UserGUID == userID).FirstOrDefaultAsync();
DocumentReference docRef = db.Collection(ServerLocation.business_notifications).Document(businessID).Collection(businessID).Document();
Dictionary<string, object> user = new Dictionary<string, object>
{
{ "notificationType", "audition" },
{ "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()},
{ "participant", userID },
{ "participantUsername", requester.Username },
{ "participantFirstname", requester.Firstname },
{ "participantSurname", requester.Surname },
{"participantThumbnail",requester.ThumbnailDp },
};
batch.Set(docRef, user);
_context.CampAds.Add(campaignAdvert);
_context.Posts.Add(newPost);
await _context.SaveChangesAsync();
await batch.CommitAsync();
}
else
{
_context.Posts.Add(newPost);
DocumentReference PostRef = db.Collection("posts").Document(newPost.PostId);
Dictionary<string, object> postActual = new Dictionary<string, object>
{
{ "playbackID", newPost.PlaybackID },
{ "timestamp",new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()},
{ "title",newPost.Title},
{ "publisher", userID },
{ "postId", newPost.PostId },
{ "aspect", post.aspect },
{ "assetID", newPost.AssetID},
{ "rendition", newPost.Rendition},
{ "campaignId",post.campaignID },
{ "likes",0},
{ "comments",0},
};
batch.Set(PostRef, postActual);
await _context.SaveChangesAsync();
await batch.CommitAsync();
}
PostedAd upload = new PostedAd();
upload.post = newPost;
upload.likes = new List<PostFav>();
upload.comments = new List<CommentsPost>();
return Ok(upload);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return StatusCode(500);
}
}
[Authorize]
[Route("add-comment"), HttpPost]
public async Task<ActionResult> CommentOnPost(CommentsPost comments)
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
string username = jwtToken.Claims.First(claim => claim.Type == "username").Value;
string dp = await _context.TesoUserDetails.AsQueryable().Where(i => i.UserGUID == userID).Select(t => t.ThumbnailDp).FirstOrDefaultAsync();
Post post = await _context.Posts.AsQueryable().Where(p => p.PostId == comments.PostId).FirstOrDefaultAsync();
_context.CommentsPosts.Add(comments);
try
{
await _context.SaveChangesAsync();
WriteBatch batch = db.StartBatch();
if (post.PublisherId != userID)
{
DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(post.PublisherId).Collection(post.PublisherId).Document(comments.CommentId);
string message = username + " commented on your post";
Dictionary<string, object> user = new Dictionary<string, object>
{
{ "notificationType", "comments" },
{ "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()},
{ "message", message },
{ "post", post.PostId},
{ "thumbnail", dp },
{"post_owner", post.PublisherId}
};
batch.Set(docRef, user);
}
DocumentReference postRef = db.Collection("posts").Document(post.PostId).Collection("comments").Document(comments.CommentId);
Dictionary<string, object> comment = new Dictionary<string, object>
{
{ "comment", comments.Comment },
{ "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()},
{ "post", post.PostId },
{ "commenter", username},
{ "commenterID", userID},
{ "commentID", comments.CommentId},
{ "thumbnail", dp },
};
batch.Set(postRef, comment);
DocumentReference PostRef = db.Collection("posts").Document(post.PostId);
Dictionary<string, object> commentUpdate = new Dictionary<string, object>
{
{ "comments", FieldValue.Increment(1) },
};
batch.Update(PostRef, commentUpdate);
await batch.CommitAsync();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return StatusCode(500);
}
return Ok();
}
[Authorize]
[Route("delete-comment"), HttpPost]
public async Task<ActionResult> DeleteCommentOnPost(CommentsPost comments)
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
string username = jwtToken.Claims.First(claim => claim.Type == "username").Value;
string dp = await _context.TesoUserDetails.AsQueryable().Where(i => i.UserGUID == userID).Select(t => t.ThumbnailDp).FirstOrDefaultAsync();
Post post = await _context.Posts.AsQueryable().Where(p => p.PostId == comments.PostId).FirstOrDefaultAsync();
_context.CommentsPosts.Remove(comments);
try
{
WriteBatch batch = db.StartBatch();
DocumentReference postRef = db.Collection("posts").Document(post.PostId).Collection("comments").Document(comments.CommentId);
batch.Delete(postRef);
DocumentReference PostRef = db.Collection("posts").Document(post.PostId);
Dictionary<string, object> commentUpdate = new Dictionary<string, object>
{
{ "comments", FieldValue.Increment(-1) },
};
batch.Update(PostRef, commentUpdate);
await batch.CommitAsync();
await _context.SaveChangesAsync();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return StatusCode(500);
}
return Ok();
}
[Authorize]
[Route("add-like"), HttpPost]
public async Task<ActionResult> LikePost(PostFav postFav)
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
string username = jwtToken.Claims.First(claim => claim.Type == "username").Value;
string dp = await _context.TesoUserDetails.AsQueryable().Where(i => i.UserGUID == userID).Select(t => t.ThumbnailDp).FirstOrDefaultAsync();
bool reward = false;
Post post = await _context.Posts.AsQueryable().Where(p => p.PostId == postFav.PostId).FirstOrDefaultAsync();
CampAd campAdvert = await _context.CampAds.AsQueryable().Where(p => p.PostId == postFav.PostId).FirstOrDefaultAsync();
WriteBatch batch = db.StartBatch();
if (campAdvert != null)
{
int currentLikes = await _context.PostFavs.AsQueryable().Where(cl => cl.PostId == postFav.PostId).CountAsync();
if ((currentLikes + 1) % 2 == 0)
{
reward = true;
}
}
if (reward)
{
CampaignFund funds = await _context.CampaignFunds.AsQueryable().Where(t => t.CampaignId == campAdvert.CampaignId).FirstOrDefaultAsync();
if (funds.CoinsAvailable.Value > 0)
{
funds.CoinsAvailable--;
UserFinance userFinance = await _context.UserFinances.AsQueryable().Where(f => f.UserGUID == post.PublisherId).FirstOrDefaultAsync();
userFinance.Gold++;
_context.UserTransactions.Add(new UserTransaction
{
CoinAmount = 1,
CoinType = "TESCNS02",
RealCash = decimal.Parse("0.0"),
Timestamp = DateTime.Now,
TransactionID = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 10000000) + userID,
UserGUID = post.PublisherId,
TransactionType = "TCT004",
Comments = "Campaign ad reward payment"
});
if (funds.CoinsAvailable == 0)
{
Campaign campaign = await _context.Campaigns.AsQueryable().Where(c => c.CampaignId == campAdvert.CampaignId).FirstOrDefaultAsync();
campaign.EndDate = DateTime.Now;
campaign.Status = "ended";
DocumentReference BusdocRef = db.Collection(ServerLocation.business_notifications).Document(campaign.BusinessId).Collection(campaign.BusinessId).Document();
Dictionary<string, object> Bususer = new Dictionary<string, object>
{
{ "notificationType", "campaign" },
{ "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()},
{ "message", $"Your campaign titled {campaign.Title} has ended as all rewards have been claimed !!!" },
};
batch.Set(BusdocRef, Bususer);
}
DocumentReference docRef2 = db.Collection(ServerLocation.user_notifications).Document(post.PublisherId).Collection(post.PublisherId).Document();
Dictionary<string, object> user2 = new Dictionary<string, object>
{
{ "notificationType", "reward" },
{ "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()},
{ "message", "Congratulations you have received 1 gold coin for an ad you posted" },
{"recipient",post.PublisherId },
{"reward","1" },
};
batch.Set(docRef2, user2);
}
}
_context.PostFavs.Add(postFav);
try
{
await _context.SaveChangesAsync();
if (post.PublisherId != userID)
{
DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(post.PublisherId).Collection(post.PublisherId).Document(postFav.CountId);
string message = username + " liked your post";
Dictionary<string, object> user = new Dictionary<string, object>
{
{ "notificationType", "likes" },
{ "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()},
{ "message", message },
{ "post", post.PostId},
{ "thumbnail", dp },
{"post_owner", post.PublisherId}
};
batch.Set(docRef, user);
}
DocumentReference postRef = db.Collection("posts").Document(post.PostId).Collection("likes").Document(postFav.CountId);
Dictionary<string, object> comment = new Dictionary<string, object>
{
{ "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()},
{ "post", JsonConvert.SerializeObject(post) },
{ "admirer", username},
{ "admirerID", userID},
{ "thumbnail", dp },
};
batch.Set(postRef, comment);
DocumentReference PostRef = db.Collection("posts").Document(post.PostId);
Dictionary<string, object> likeUpdate = new Dictionary<string, object>
{
{ "likes", FieldValue.Increment(1) },
};
batch.Update(PostRef, likeUpdate);
await batch.CommitAsync();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return StatusCode(500);
}
return Ok();
}
[Authorize]
[Route("remove-like"), HttpPost]
public async Task<ActionResult> UnLikePost([FromBody] string postID)
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
string username = jwtToken.Claims.First(claim => claim.Type == "username").Value;
string dp = await _context.TesoUserDetails.AsQueryable().Where(i => i.UserGUID == userID).Select(t => t.ThumbnailDp).FirstOrDefaultAsync();
PostFav postFav = await _context.PostFavs.AsQueryable().Where(p => p.AdmirerId == userID && p.PostId == postID).FirstOrDefaultAsync();
Post post = await _context.Posts.AsQueryable().Where(p => p.PostId == postFav.PostId).FirstOrDefaultAsync();
_context.PostFavs.Remove(postFav);
try
{
WriteBatch batch = db.StartBatch();
DocumentReference postRef = db.Collection("posts").Document(post.PostId).Collection("likes").Document(postFav.CountId);
batch.Delete(postRef);
DocumentReference PostRef = db.Collection("posts").Document(post.PostId);
Dictionary<string, object> likeUpdate = new Dictionary<string, object>
{
{ "likes", FieldValue.Increment(-1) },
};
batch.Update(PostRef, likeUpdate);
await _context.SaveChangesAsync();
await batch.CommitAsync();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return StatusCode(500);
}
return Ok();
}
[Authorize]
[Route("delete-post"), HttpPost]
public async Task<ActionResult> DeletePost(Post posts)
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
string username = jwtToken.Claims.First(claim => claim.Type == "username").Value;
string dp = await _context.TesoUserDetails.AsQueryable().Where(i => i.UserGUID == userID).Select(t => t.ThumbnailDp).FirstOrDefaultAsync();
PostFav fav = await _context.PostFavs.AsQueryable().Where(p => p.PostId == posts.PostId).FirstOrDefaultAsync();
CommentsPost comment = await _context.CommentsPosts.AsQueryable().Where(p => p.PostId == posts.PostId).FirstOrDefaultAsync();
PendingDeleteFile deleteFile = new PendingDeleteFile();
deleteFile.DateDeleted = DateTime.Now;
deleteFile.Filename = posts.PlaybackID;
deleteFile.CountId = "TESADSDEL" + String.Format("{0:d6}", (DateTime.Now.Ticks / 10) % 100000);
_context.Posts.Remove(posts);
if (fav != null)
_context.PostFavs.Remove(fav);
if (comment != null)
_context.CommentsPosts.Remove(comment);
_context.PendingDeleteFiles.Add(deleteFile);
try
{
DocumentReference postRef = db.Collection("posts").Document(posts.PostId);
await _context.SaveChangesAsync();
await postRef.DeleteAsync();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return StatusCode(500);
}
return Ok();
}
[Authorize]
[Route("view-post"), HttpPost]
public async Task<ActionResult> WatchPost([FromBody] string postID)
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
string username = jwtToken.Claims.First(claim => claim.Type == "username").Value;
if(_context.PostViews.Any(i => i.PostId == postID && i.UserGuid == userID))
{
return Ok();
}
_context.PostViews.Add(new PostView
{
CountId = postID + userID + DateTime.Now,
Timestamp = DateTime.Now,
PostId = postID,
UserGuid = userID
});
try
{
await _context.SaveChangesAsync();
}
catch
{
}
return Ok();
}
[Authorize]
[Route("getrendition"), HttpPost]
public async Task<ActionResult<string>> GetRendtion([FromBody] string id)
{
return await _context.Posts.AsQueryable().Where(p => p.PostId == id).Select(s=>s.Rendition).FirstOrDefaultAsync();
}
[Authorize]
[Route("flag-post"), HttpPost]
public async Task<ActionResult> ReportPost(ReportedContent reported)
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
string username = jwtToken.Claims.First(claim => claim.Type == "username").Value;
ReportedContent content = new ReportedContent {
PostId = reported.PostId,
PublisherId = reported.PublisherId,
Report = reported.Report,
Timestamp = DateTime.Now,
UserGuid = userID
};
_context.ReportedContents.Add(content);
try
{
await _context.SaveChangesAsync();
}
catch
{
return StatusCode(500);
}
return Ok();
}
[Authorize]
[Route("unflag-post"), HttpPost]
public async Task<ActionResult> UnflagPost([FromBody] string postID)
{
var accessToken = Request.Headers[HeaderNames.Authorization];
string token = accessToken;
token = token.Substring(6).Trim();
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadToken(token) as JwtSecurityToken;
string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value;
string username = jwtToken.Claims.First(claim => claim.Type == "username").Value;
ReportedContent content = await _context.ReportedContents.AsQueryable().Where(e => e.PostId == postID && e.UserGuid == userID).FirstOrDefaultAsync();
_context.ReportedContents.Remove(content);
try
{
await _context.SaveChangesAsync();
}
catch
{
return StatusCode(500);
}
return Ok();
}
private static async Task DeleteCollection(CollectionReference collectionReference, int batchSize)
{
QuerySnapshot snapshot = await collectionReference.Limit(batchSize).GetSnapshotAsync();
IReadOnlyList<DocumentSnapshot> documents = snapshot.Documents;
while (documents.Count > 0)
{
foreach (DocumentSnapshot document in documents)
{
Console.WriteLine("Deleting document {0}", document.Id);
await document.Reference.DeleteAsync();
}
snapshot = await collectionReference.Limit(batchSize).GetSnapshotAsync();
documents = snapshot.Documents;
}
Console.WriteLine("Finished deleting all documents from the collection.");
}
}
}