Skip to content

Commit

Permalink
feat(ads): add options to getRandom function
Browse files Browse the repository at this point in the history
Now accepts additional options for filtering the results.

The options include ignoreId, ownerId, and tryOtherOwners.

This allows for more flexibility in retrieving random advertisements based on specific criteria.
  • Loading branch information
aprendendofelipe committed Jul 18, 2024
1 parent 49e8e5a commit b37727a
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 6 deletions.
20 changes: 18 additions & 2 deletions models/advertisement.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import database from 'infra/database';

async function getRandom(limit) {
async function getRandom(limit, options = {}) {
const { ignoreId, ownerId, tryOtherOwners } = options;

const query = {
values: [limit],
};

let where = "type = 'ad' AND status = 'published'";

if (ownerId) {
where += ` AND c.owner_id = '${ownerId}'`;
}

if (ignoreId) {
where += ` AND c.id != '${ignoreId}'`;
}

query.text = `
SELECT
c.id,
Expand All @@ -15,13 +27,17 @@ async function getRandom(limit) {
'markdown' as ad_type
FROM contents c
INNER JOIN users u ON c.owner_id = u.id
WHERE type = 'ad' AND status = 'published'
WHERE ${where}
ORDER BY RANDOM()
LIMIT $1;
`;

const results = await database.query(query);

if (!results.rows.length && ownerId && tryOtherOwners) {
return getRandom(limit, { ignoreId });
}

return results.rows;
}

Expand Down
14 changes: 14 additions & 0 deletions models/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,20 @@ const schemas = {
});
},

ignore_id: function () {
return Joi.object({
ignore_id: schemas.id().extract('id'),
});
},

flexible: function () {
return Joi.object({
flexible: Joi.boolean()
.default(false)
.when('$required.optional', { is: 'required', then: Joi.required(), otherwise: Joi.optional() }),
});
},

where: function () {
let whereSchema = Joi.object({}).optional().min(1);

Expand Down
6 changes: 5 additions & 1 deletion pages/[username]/[slug]/index.public.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,11 @@ export const getStaticProps = getStaticPropsRevalidate(async (context) => {
secureParentContentFound.body = removeMarkdown(secureParentContentFound.body, { maxLength: 50 });
}

const adsFound = await ad.getRandom(1);
const adsFound = await ad.getRandom(1, {
ignoreId: secureContentFound.id,
ownerId: secureContentFound.owner_id,
tryOtherOwners: secureContentFound.type === 'content',
});
const secureAdValues = authorization.filterOutput(userTryingToGet, 'read:ad:list', adsFound);

return {
Expand Down
9 changes: 8 additions & 1 deletion pages/api/v1/sponsored-beta/index.public.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export default nextConnect({
function getValidationHandler(request, response, next) {
const cleanValues = validator(request.query, {
per_page: 'optional',
owner_id: 'optional',
ignore_id: 'optional',
flexible: 'optional',
});

request.query = cleanValues;
Expand All @@ -29,7 +32,11 @@ function getValidationHandler(request, response, next) {
async function getHandler(request, response) {
const userTryingToList = user.createAnonymous();

const ads = await ad.getRandom(request.query.per_page);
const ads = await ad.getRandom(request.query.per_page, {
ignoreId: request.query.ignore_id,
ownerId: request.query.owner_id,
tryOtherOwners: request.query.flexible,
});

const secureOutputValues = authorization.filterOutput(userTryingToList, 'read:ad:list', ads);

Expand Down
56 changes: 54 additions & 2 deletions tests/integration/api/v1/sponsored-beta/get.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,64 @@ describe('GET /api/v1/sponsored-beta', () => {
expect(createdAds).toContainEqual(responseBody[0]);
expect(createdAds).toContainEqual(responseBody[1]);
});

it('should ignore specific ad', async () => {
const createdAds = await createAds(1, owner);

const { response, responseBody } = await adsRequestBuilder.get(`?ignore_id=${createdAds[0].id}`);

expect.soft(response.status).toBe(200);
expect(responseBody).toEqual([]);
});

it('should get from specific owner', async () => {
const specificOwner = await orchestrator.createUser();

orchestrator.createBalance({
balanceType: 'user:tabcash',
recipientId: specificOwner.id,
amount: defaultTabCashForAdCreation,
});

await createAds(10, owner);
const specificAd = await createAds(1, specificOwner);
await createAds(10, owner, 10);

const { response, responseBody } = await adsRequestBuilder.get(`?owner_id=${specificOwner.id}`);

expect.soft(response.status).toBe(200);
expect(responseBody).toStrictEqual(specificAd);
});

it('should try get from another owner', async () => {
const specificOwner = await orchestrator.createUser();

const createdAds = await createAds(1, owner);

const { response, responseBody } = await adsRequestBuilder.get(`?flexible=true&owner_id=${specificOwner.id}`);

expect.soft(response.status).toBe(200);
expect(responseBody).toStrictEqual(createdAds);
});

it('should try get from another owner and ignore specific ad', async () => {
const specificOwner = await orchestrator.createUser();

const createdAds = await createAds(2, owner);

const { response, responseBody } = await adsRequestBuilder.get(
`?flexible=true&owner_id=${specificOwner.id}&ignore_id=${createdAds[1].id}`,
);

expect.soft(response.status).toBe(200);
expect(responseBody).toStrictEqual([createdAds[0]]);
});
});
});

async function createAds(count, owner) {
async function createAds(count, owner, indexOffset = 0) {
const ads = [];
for (let i = 0; i < count; i++) {
for (let i = indexOffset; i < count + indexOffset; i++) {
const ad = await orchestrator.createContent({
owner_id: owner.id,
title: `Ad #${i}`,
Expand Down

0 comments on commit b37727a

Please sign in to comment.