public async Task ClearNotificationsAsync(WatchView watch, long uid)
    {
        using var search = dbFactory.CreateSearch();
        var getRequest = new Func <string, SearchRequest>(t => new SearchRequest()
        {
            type   = t,
            fields = "id,contentId",
            query  = "contentId = @cid",
            order  = "id_desc",
            limit  = 1
        });
        var getValues = new Func <Dictionary <string, object> >(() => new Dictionary <string, object> {
            { "cid", watch.contentId }
        });

        //Need the latest values for comment and activity. Don't care if message is a module
        //message, the id will still be valid for tracking purposes
        var messages = await search.SearchSingleType <MessageView>(uid, getRequest("message"), getValues());

        var activity = await search.SearchSingleType <ActivityView>(uid, getRequest("activity"), getValues());

        if (messages.Count > 0)
        {
            watch.lastCommentId = messages.First().id;
        }
        if (activity.Count > 0)
        {
            watch.lastActivityId = activity.First().id;
        }
    }
Exemplo n.º 2
0
    public async Task <LiveEventCachedData> LookupEventDataAsync(LiveEvent evnt)
    {
        var requests = GetSearchRequestsForEvents(new List <LiveEvent> {
            evnt
        });

        using var search = dbFactory.CreateSearch();

        var searchData = await search.SearchUnrestricted(requests);

        return(new LiveEventCachedData()
        {
            evnt = evnt, data = searchData.objects
        });
    }
Exemplo n.º 3
0
    public GenericSearcher GetGenericSearcher()
    {
        var searcher = (GenericSearcher)dbFactory.CreateSearch();

        spawnedSearches.Add(searcher);
        return(searcher);
    }
Exemplo n.º 4
0
    /// <summary>
    /// Using the given argument information, fill (as in actually mutate) the given list of argument values
    /// </summary>
    /// <param name="argumentInfos"></param>
    /// <param name="arglist"></param>
    /// <param name="existingArgs"></param>
    public void ParseArgs(ModuleSubcommandInfo subcommandInfo, string arglist, List <object> existingArgs)
    {
        using var search = dbFactory.CreateSearch();
        var forcedFinal = false;

        foreach (var argInfo in subcommandInfo.Arguments)
        {
            //forcedFinal is specifically for "freeform" arguments, which MUST come at the end! It just
            //eats up the rest of the input
            if (forcedFinal)
            {
                throw new InvalidOperationException("No argument can come after a 'freeform' argument!");
            }

            //Kind of wasteful, but just easier to always start with a clean slate after ripping args out
            arglist = arglist.Trim();

            //Matcher function for generic regex matches. Useful for words, users, etc.
            Action <string, Action <Match> > genericMatch = (r, a) =>
            {
                var regex = new Regex(r, RegexOptions.Compiled | RegexOptions.IgnoreCase);
                var match = regex.Match(arglist);

                //An argument of a given type must ALWAYS be a pure match.
                if (!match.Success)
                {
                    throw new RequestException($"Parse error in argument '{argInfo?.name}', not of type '{argInfo?.type}'");
                }

                //Get rid of the argument from the remaining arglist
                arglist = regex.Replace(arglist, "");

                //Try to do whatever the user wanted (probably adding to existingArgs)
                try
                {
                    a(match);
                }
                catch (Exception ex)
                {
                    throw new RequestException($"{ex.Message} (Parse error in argument '{argInfo?.name}' of type '{argInfo?.type}')", ex);
                }
            };

            //Parse arguments differently based on type
            switch (argInfo?.type)
            {
            case "user":
                genericMatch(@"^([0-9]+)(\([^\s]+\))?", m => {
                    //Check if user exists!
                    var uid = long.Parse(m.Groups[1].Value);
                    //Yes this is BLOCKING, this entire module system is blocking because lua/etc
                    //var users = userSource.SimpleSearchAsync(new UserSearch() { Ids = new List<long>{uid}}).Result;
                    try {
                        var user = search.GetById <UserView>(RequestType.user, uid);
                    }
                    catch (NotFoundException ex) {
                        throw new RequestException($"User not found: {uid}", ex);
                    }
                    existingArgs.Add(uid);
                });
                break;

            case "int":
                // This will throw an exception on error, not telling the user much
                genericMatch(@"^([0-9]+)(\([^\s]+\))?", m => { existingArgs.Add(long.Parse(m.Groups[1].Value)); });
                break;

            case "word":
                genericMatch(@"^([^\s]+)", m => { existingArgs.Add(m.Groups[1].Value); });
                break;

            case "freeform":
                existingArgs.Add(arglist);     //Just append whatever is left
                forcedFinal = true;
                break;

            default:
                throw new InvalidOperationException($"Unknown argument type: {argInfo?.type} ({argInfo?.name})");
            }
        }
    }
Exemplo n.º 5
0
    public async Task <Tuple <byte[], string> > GetFileAsync(string hash, GetFileModify modify)
    {
        if (modify.size > 0)
        {
            if (modify.size < 10)
            {
                throw new RequestException("Requested file size too small!");
            }
            else if (modify.size <= 100)
            {
                modify.size = 10 * (modify.size / 10);
            }
            else if (modify.size <= 1000)
            {
                modify.size = 100 * (modify.size / 100);
            }
            else
            {
                throw new RequestException("Requested file size too large!");
            }
        }

        //Go get that ONE file. This should return null if we can't read it... let's hope!
        //SPECIAL: the 0 file is
        ContentView?fileData = null;

        if (hash == Constants.DefaultHash)
        {
            fileData = new ContentView()
            {
                id = 0, literalType = FallbackMime, hash = hash, contentType = InternalContentType.file
            };
        }
        else
        {
            //Doesn't matter who the requester is, ANY file with this hash is fine... what about deleted though?
            using var searcher = dbFactory.CreateSearch();
            fileData           = (await searcher.GetByField <ContentView>(RequestType.content, "hash", hash)).FirstOrDefault();
        }

        if (fileData == null || fileData.deleted || fileData.contentType != InternalContentType.file)
        {
            throw new NotFoundException($"Couldn't find file data with hash {hash}");
        }

        var thumbnailPath = GetThumbnailPath(hash, modify);
        var mimeType      = fileData.literalType ?? "";

        try
        {
            //This means they're requesting a MAIN data, just go get it
            if (string.IsNullOrEmpty(thumbnailPath))
            {
                return(Tuple.Create(await GetMainDataAsync(hash), mimeType));
            }
            else
            {
                return(Tuple.Create(await GetThumbnailAsync(hash, thumbnailPath, modify), mimeType));
            }
        }
        catch (NotFoundException)
        {
            //This just means we CAN generate it!
            if (hash == Constants.DefaultHash && !string.IsNullOrWhiteSpace(config.DefaultImageFallback))
            {
                logger.LogInformation($"Creating default image {hash} from base64 string given in config");
                await SaveMainDataAsync(Convert.FromBase64String(config.DefaultImageFallback), hash, mimeType);

                return(await GetFileAsync(hash, modify));
            }
            else
            {
                throw;
            }
        }
    }