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.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>> 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 postedAds = new List(); List 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>> UserPost([FromBody] string id) { List postedAds = new List(); List posts = await _context.Posts.AsQueryable().Where(i => i.PublisherId == id).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("homefeed"), HttpPost] public async Task>> 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; List postedAds = new List(); List posts = await _context.Posts.AsQueryable().Where(i => i.PublisherId != userID).OrderByDescending(t => t.Timestamp).Take(100).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).AsNoTracking().ToListAsync(); upload.comments = await _context.CommentsPosts.AsQueryable().Where(c => c.PostId == post.PostId).AsNoTracking().ToListAsync(); upload.campaignAd = await _context.CampAds.AsQueryable().AnyAsync(p => p.PostId == post.PostId); upload.publisher = await (from u in _context.TesoUserDetails.AsQueryable() join e in _context.UserFinances on u.UserGUID equals e.UserGUID into finances from fnc in finances.DefaultIfEmpty() where u.UserGUID == post.PublisherId select new TesoUser() { username = u.Username, address = u.Address, country = u.Country, thumbnail_dp = u.ThumbnailDp, DateOfBirth = u.DateOfBirth, description = u.Description, email = u.Email, firstname = u.Firstname, friends = "0", gender = u.Gender, gold = fnc.UserGUID != null ? fnc.Gold.ToString() : "0", silver = fnc.UserGUID != null ? fnc.Silver.ToString() : "0", lastname = u.Surname, phonenumber = u.Phonenumber.ToString(), userGUID = u.UserGUID }).AsNoTracking().FirstOrDefaultAsync(); 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("upload-post"), HttpPost] [RequestSizeLimit(524288000)] public async Task UploadPost([FromForm] 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; var file = post.video; if (file == null) { return new UnsupportedMediaTypeResult(); } Post newPost = new Post(); newPost.Path = DateTime.Now.ToString("yyyyMMddHHmmssfff") + userID.Trim() + ".mp4"; newPost.Title = post.title; newPost.Timestamp = DateTime.Now; newPost.PublisherId = userID; newPost.PostId = "TESADS" + String.Format("{0:d6}", (DateTime.Now.Ticks / 10) % 100000); newPost.Thumbnail = post.thumbnail; newPost.Aspect = post.aspect; using (var fileStream = new FileStream(ServerLocation.videoAds + newPost.Path, FileMode.Create)) { await file.CopyToAsync(fileStream); } //await FFMpegArguments //.FromFileInput(ServerLocation.videoAds + "raw" + newPost.Path) //.OutputToFile(ServerLocation.videoAds + newPost.Path, false, options => options // // .WithVideoCodec(VideoCodec.LibX264) // //.WithConstantRateFactor(21) // //.WithAudioCodec(AudioCodec.Aac) // //.WithVariableBitrate(4) // //.WithVideoFilters(filterOptions => filterOptions // // .Scale(VideoSize.Original)) // .WithFastStart()) //.ProcessAsynchronously(); WriteBatch batch = db.StartBatch(); DocumentReference PostRef = db.Collection("posts").Document(newPost.PostId); Dictionary postActual = new Dictionary { { "path", newPost.Path }, { "timestamp",new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "title",newPost.Title}, { "publisher", userID }, { "postId", newPost.PostId }, { "aspect", post.aspect }, { "thumbnail", newPost.Thumbnail}, {"campaignId",post.campaignID }, {"likes",0}, {"comments",0}, }; batch.Set(PostRef, postActual); 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 user = new Dictionary { { "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); await _context.SaveChangesAsync(); await batch.CommitAsync(); } return Ok(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); return StatusCode(500); } } [Authorize] [Route("add-comment"), HttpPost] public async Task 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 user = new Dictionary { { "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 comment = new Dictionary { { "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 commentUpdate = new Dictionary { { "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 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 commentUpdate = new Dictionary { { "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 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 Bususer = new Dictionary { { "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 user2 = new Dictionary { { "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 user = new Dictionary { { "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 comment = new Dictionary { { "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 likeUpdate = new Dictionary { { "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 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 likeUpdate = new Dictionary { { "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 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.Path; 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); //CollectionReference postRefComments = db.Collection("posts").Document("comments").Collection(posts.PostId); await _context.SaveChangesAsync(); await postRef.DeleteAsync(); //await DeleteCollection(postRefLikes, 10); //await DeleteCollection(postRefComments, 10); } catch (Exception e) { Console.WriteLine(e.ToString()); return StatusCode(500); } return Ok(); } private static async Task DeleteCollection(CollectionReference collectionReference, int batchSize) { QuerySnapshot snapshot = await collectionReference.Limit(batchSize).GetSnapshotAsync(); IReadOnlyList 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."); } } }