private async Task <IEnumerable <CollectionItem> > _filterAudience(string user, bool isOwner, int dbId, int count, int under = int.MaxValue, int above = int.MinValue, RelevantEntitiesService.IQueryStatement query = null) { var postfix = "order by \"CollectionItemId\" desc " + (count > 0 ? $"limit {count}" : ""); if (isOwner && query == null) { return(await _connection.QueryAsync <CollectionItem>("select * from \"CollectionItems\" WHERE \"CollectionItemId\" < @Under and \"CollectionItemId\" > @Above and \"CollectionId\" = @DbId " + postfix, new { Under = under, Above = above, DbId = dbId })); } int?userId = null; if (user != null) { userId = await _entityStore.ReverseAttribute(user, false); } if (userId == null && query == null) { return(await _connection.QueryAsync <CollectionItem>("select * from \"CollectionItems\" WHERE \"CollectionItemId\" < @Under and \"CollectionItemId\" > @Above and \"IsPublic\" = TRUE and \"CollectionId\" = @DbId " + postfix, new { Under = under, Above = above, DbId = dbId })); } var ids = new List <int>(); foreach (var audienceId in _audienceIds) { var id = await _entityStore.ReverseAttribute(audienceId, false); if (id.HasValue) { ids.Add(id.Value); } } var queryMap = new Dictionary <string, int>(); if (query != null) { foreach (var typeId in query.RequiredProperties) { var id = await _entityStore.ReverseAttribute(typeId, true); queryMap[typeId] = id.Value; } } // select c.* from "CollectionItems" c, "TripleEntities" e WHERE e."EntityId" = c."ElementId" and "CollectionItemId" < @Under and exists(select 1 from "Triples" where "PredicateId" = any(@Ids) and "AttributeId" = @UserId and "SubjectId" = e."IdId" and "SubjectEntityId" = e."EntityId" limit 1) return(await _connection.QueryAsync <CollectionItem>( "select c.* from \"CollectionItems\" c, \"TripleEntities\" a WHERE a.\"EntityId\" = c.\"ElementId\" and \"CollectionItemId\" < @Under and \"CollectionItemId\" > @Above and \"CollectionId\" = @DbId " + (isOwner ? "" : userId == null ? " and c.\"IsPublic\" = true" : "and exists(select 1 from \"Triples\" where \"PredicateId\" = any(@Ids) and \"AttributeId\" = @UserId and \"SubjectId\" = a.\"IdId\" and \"SubjectEntityId\" = a.\"EntityId\" limit 1) ") + (query == null ? " " : $" and {query.BuildSQL(queryMap)} ") + "order by c.\"CollectionItemId\" desc " + (count > 0 ? $"limit {count}" : ""), new { Under = under, Above = above, Ids = ids, UserId = userId ?? 0, DbId = dbId } )); }
private async Task <IActionResult> _timeline <T>(string id, string max_id, string since_id, int limit, _processItem <T> process, RelevantEntitiesService.IQueryStatement query = null) { if (!int.TryParse(max_id, out var fromId)) { fromId = int.MaxValue; } if (!int.TryParse(since_id, out var toId)) { toId = int.MinValue; } limit = Math.Min(40, Math.Max(20, limit)); var parsed = new List <T>(); string links = null; while (parsed.Count < limit) { var items = await _collectionTools.GetItems(id, fromId, toId, limit + 1, query ?? new RelevantEntitiesService.ContainsAnyStatement("rdf:type") { "https://www.w3.org/ns/activitystreams#Create", "https://www.w3.org/ns/activitystreams#Announce" }); if (items.Count == 0) { break; } if (links == null) { links = $"<{Request.Scheme}://{Request.Host.ToUriComponent()}{Request.Path}?since_id={items[0].CollectionItemId}>; rel=\"prev\""; } foreach (var item in items) { if (parsed.Count >= limit) { links += $", <{Request.Scheme}://{Request.Host.ToUriComponent()}{Request.Path}?max_id={item.CollectionItemId}>; rel=\"next\""; break; } try { var translated = await process(item); if (translated != null) { parsed.Add(translated); } } catch (Exception e) { Console.WriteLine(e); } toId = int.MinValue; fromId = item.CollectionItemId; } } if (links != null) { Response.Headers.Add("Link", links); } return(Json(parsed)); }
public async Task <List <EntityCollectionItem> > GetItems(string id, int fromId = int.MaxValue, int toId = int.MinValue, int count = 10, RelevantEntitiesService.IQueryStatement query = null) { var isOwner = false; var entity = await _entityStore.GetEntity(id, false); var user = _getUser(); if (entity != null && entity.Data["attributedTo"].Any(a => a.Id == user)) { isOwner = true; } var entities = await _filterAudience(user, isOwner, entity.DbId, count, fromId, toId, query); return((await _entityStore.GetEntities(entities.Select(a => a.ElementId).ToList())).Zip(entities, (a, b) => new EntityCollectionItem { CollectionItemId = b.CollectionItemId, Entity = a }).ToList()); }