Add "Gallery" field to return multiple images in 1 post (#242)
All checks were successful
Stage / build (push) Successful in 8s
Stage / rsync (push) Successful in 6s

# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Added a `Gallery` option to the return parameters, which will be an array of image links for every image of that post
- The JSON will always show it
- The human readable will only show it if there is more than 1 image

#161

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)
- [x] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

- Added new unit tests for these changes

# Checklist

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that provide my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream modules

Reviewed-on: #242
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
This commit is contained in:
Ethan Lane 2024-10-26 22:00:55 +01:00 committed by Vylpes
parent db35dee5f9
commit 4b9c8a8ea5
9 changed files with 95 additions and 21 deletions

View file

@ -26,6 +26,7 @@ $ random-bunny
Archived = false Archived = false
Author = Rabbit_Owner Author = Rabbit_Owner
Downvotes = 0 Downvotes = 0
Gallery = https://i.redd.it/sfz0srdrimjc1.png, https://i.redd.it/sfz0srdrimjc1.png
Hidden = false Hidden = false
Permalink = /r/Rabbits/comments/1av1rg9/cute_baby_bun/ Permalink = /r/Rabbits/comments/1av1rg9/cute_baby_bun/
Subreddit = Rabbits Subreddit = Rabbits
@ -35,6 +36,8 @@ Upvotes = 211
Url = https://i.redd.it/sfz0srdrimjc1.png Url = https://i.redd.it/sfz0srdrimjc1.png
``` ```
- The `Gallery` field is only shown when there is more than 1 image returned, which then the `Url` field is the first image of that list.
## Help ## Help
The command also includes a help option in case you are stuck. The command also includes a help option in case you are stuck.
@ -72,9 +75,11 @@ $ random-bunny --json
$ randon-bunny -j $ randon-bunny -j
{"Archived":false,"Author":"Rabbit_Owner","Downs":0,"Hidden":false,"Permalink":"/r/Rabbits/comments/1av1rg9/cute_baby_bun/","Subreddit":"Rabbits","SubredditSubscribers":486085,"Title":"Cute baby bun","Ups":210,"Url":"https://i.redd.it/sfz0srdrimjc1.png"} {"Archived":false,"Author":"Rabbit_Owner","Downs":0,"Hidden":false,"Permalink":"/r/Rabbits/comments/1av1rg9/cute_baby_bun/","Subreddit":"Rabbits","SubredditSubscribers":486085,"Title":"Cute baby bun","Ups":210,"Url":"https://i.redd.it/sfz0srdrimjc1.png","Gallery":["https://i.redd.it/sfz0srdrimjc1.png"]}
``` ```
- The `Url` field is the first image of the `Gallery` array
## Sort ## Sort
You can also choose the sorting option which reddit will use to return the available posts to randomise from. You can also choose the sorting option which reddit will use to return the available posts to randomise from.

View file

@ -39,6 +39,7 @@ The json string which gets returned consists of:
- archived - archived
- author - author
- downs - downs
- gallery
- hidden - hidden
- permalink - permalink
- subreddit - subreddit

View file

@ -2,11 +2,12 @@ export default interface IRedditResult {
Archived: boolean, Archived: boolean,
Author: string, Author: string,
Downs: number, Downs: number,
Gallery: string[],
Hidden: boolean, Hidden: boolean,
Permalink: string, Permalink: string,
Subreddit: string, Subreddit: string,
SubredditSubscribers: number, SubredditSubscribers: number,
Title: string, Title: string,
Ups: number, Ups: number,
Url: string Url: string,
} }

View file

@ -2,17 +2,19 @@ import fetch from "got-cjs";
import * as htmlparser from "htmlparser2"; import * as htmlparser from "htmlparser2";
export default class ImageHelper { export default class ImageHelper {
public static async FetchImageFromRedditGallery(url: string): Promise<string | undefined> { public static async FetchImageFromRedditGallery(url: string): Promise<string[]> {
const fetched = await fetch(url); const fetched = await fetch(url);
if (!fetched || fetched.errored || fetched.statusCode != 200) { if (!fetched || fetched.errored || fetched.statusCode != 200) {
return undefined; return [];
} }
const dom = htmlparser.parseDocument(fetched.body); const dom = htmlparser.parseDocument(fetched.body);
const img = htmlparser.DomUtils.findOne((x => x.tagName == "img" && x.attributes.find(y => y.value.includes("https://preview.redd.it")) != null), dom.children, true); const img = htmlparser.DomUtils.findAll((x => x.tagName == "img" && x.attributes.find(y => y.value.includes("https://preview.redd.it")) != null), dom.children);
const imgSrc = img?.attributes.find(x => x.name == "src")?.value; const imgSrc = img
.flatMap(x => x.attributes.find(x => x.name == "src")?.value)
.filter(x => x != undefined);
return imgSrc; return imgSrc;
} }

View file

@ -14,7 +14,13 @@ export default class OutputHelper {
outputLines.push(`Archived = ${result.Archived}`); outputLines.push(`Archived = ${result.Archived}`);
outputLines.push(`Author = ${result.Author}`); outputLines.push(`Author = ${result.Author}`);
outputLines.push(`Downvotes = ${result.Downs}`); outputLines.push(`Downvotes = ${result.Downs}`);
if (result.Gallery.length > 1) {
outputLines.push(`Gallery = ${result.Gallery.join(", ")}`);
}
outputLines.push(`Hidden = ${result.Hidden}`); outputLines.push(`Hidden = ${result.Hidden}`);
outputLines.push(`Permalink = ${result.Permalink}`); outputLines.push(`Permalink = ${result.Permalink}`);
outputLines.push(`Subreddit = ${result.Subreddit}`); outputLines.push(`Subreddit = ${result.Subreddit}`);
outputLines.push(`Subreddit Subscribers = ${result.SubredditSubscribers}`); outputLines.push(`Subreddit Subscribers = ${result.SubredditSubscribers}`);
@ -22,6 +28,7 @@ export default class OutputHelper {
outputLines.push(`Upvotes = ${result.Ups}`); outputLines.push(`Upvotes = ${result.Ups}`);
outputLines.push(`Url = ${result.Url}`); outputLines.push(`Url = ${result.Url}`);
if (options.queryMetadata != null) { if (options.queryMetadata != null) {
outputLines.push(`Query.Subreddit = ${response.Query.subreddit}`); outputLines.push(`Query.Subreddit = ${response.Query.subreddit}`);
outputLines.push(`Query.Sort By = ${response.Query.sortBy}`); outputLines.push(`Query.Sort By = ${response.Query.sortBy}`);

View file

@ -93,6 +93,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho
const randomData = randomSelect.data; const randomData = randomSelect.data;
let url: string; let url: string;
let gallery: string[];
if (randomData.url.includes("/gallery")) { if (randomData.url.includes("/gallery")) {
const galleryImage = await ImageHelper.FetchImageFromRedditGallery(randomData.url); const galleryImage = await ImageHelper.FetchImageFromRedditGallery(randomData.url);
@ -112,9 +113,11 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho
} }
} }
url = galleryImage; url = galleryImage[0];
gallery = galleryImage;
} else { } else {
url = randomData.url; url = randomData.url;
gallery = [randomData.url];
} }
const redditResult: IRedditResult = { const redditResult: IRedditResult = {
@ -128,6 +131,7 @@ export default async function randomBunny(subreddit: string, sortBy: "new" | "ho
Title: randomData['title'], Title: randomData['title'],
Ups: randomData['ups'], Ups: randomData['ups'],
Url: url, Url: url,
Gallery: gallery,
}; };
return { return {

View file

@ -13,7 +13,7 @@ Upvotes = 17
Url = https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d" Url = https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d"
`; `;
exports[`GenerateOutput GIVEN options.json is true, EXPECT output to be returned as JSON 1`] = `"{"Archived":false,"Author":"author","Downs":0,"Hidden":false,"Permalink":"/r/Rabbits/comments/1dj8pbt/this_is_my_ms_bear/","Subreddit":"Rabbits","SubredditSubscribers":654751,"Title":"This is my Ms Bear!","Ups":17,"Url":"https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d"}"`; exports[`GenerateOutput GIVEN options.json is true, EXPECT output to be returned as JSON 1`] = `"{"Archived":false,"Author":"author","Downs":0,"Hidden":false,"Permalink":"/r/Rabbits/comments/1dj8pbt/this_is_my_ms_bear/","Subreddit":"Rabbits","SubredditSubscribers":654751,"Title":"This is my Ms Bear!","Ups":17,"Url":"https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d","Gallery":["https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d"]}"`;
exports[`GenerateOutput GIVEN options.queryMetadata is supplied, EXPECT query metadata to be added 1`] = ` exports[`GenerateOutput GIVEN options.queryMetadata is supplied, EXPECT query metadata to be added 1`] = `
"Archived = false "Archived = false
@ -30,3 +30,17 @@ Query.Subreddit = rabbits
Query.Sort By = hot Query.Sort By = hot
Query.Limit = 100" Query.Limit = 100"
`; `;
exports[`GenerateOutput GIVEN the Gallery input has more than 1 item, EXPECT Gallery line to be added 1`] = `
"Archived = false
Author = author
Downvotes = 0
Gallery = https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d, https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d
Hidden = false
Permalink = /r/Rabbits/comments/1dj8pbt/this_is_my_ms_bear/
Subreddit = Rabbits
Subreddit Subscribers = 654751
Title = This is my Ms Bear!
Upvotes = 17
Url = https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d"
`;

View file

@ -17,18 +17,19 @@ describe("FetchImageFromRedditGallery", () => {
expect(fetchMock).toHaveBeenCalledTimes(1); expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith("https://redd.it/gallery/image"); expect(fetchMock).toHaveBeenCalledWith("https://redd.it/gallery/image");
expect(result).toBe("https://preview.redd.it/image.png"); expect(result.length).toBe(1);
expect(result[0]).toBe("https://preview.redd.it/image.png");
}); });
test("GIVEN fetch is unable to return data, EXPECT undefined returned", async () => { test("GIVEN fetch is unable to return data, EXPECT empty array returned", async () => {
fetchMock.mockResolvedValue(null); fetchMock.mockResolvedValue(null);
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image"); const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined(); expect(result.length).toBe(0);
}); });
test("GIVEN fetch is an error, EXPECT undefined returned", async () => { test("GIVEN fetch is an error, EXPECT empty array returned", async () => {
fetchMock.mockResolvedValue({ fetchMock.mockResolvedValue({
body: "<html><body><img src='https://preview.redd.it/image.png' /></body></html>", body: "<html><body><img src='https://preview.redd.it/image.png' /></body></html>",
errored: "Error", errored: "Error",
@ -37,10 +38,10 @@ describe("FetchImageFromRedditGallery", () => {
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image"); const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined(); expect(result.length).toBe(0);
}); });
test("GIVEN fetch is not status code of 200, EXPECT undefined returned", async () => { test("GIVEN fetch is not status code of 200, EXPECT empty array returned", async () => {
fetchMock.mockResolvedValue({ fetchMock.mockResolvedValue({
body: "<html><body><img src='https://preview.redd.it/image.png' /></body></html>", body: "<html><body><img src='https://preview.redd.it/image.png' /></body></html>",
errored: undefined, errored: undefined,
@ -49,10 +50,10 @@ describe("FetchImageFromRedditGallery", () => {
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image"); const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined(); expect(result.length).toBe(0);
}); });
test("GIVEN image tag is not found, EXPECT undefined returned", async () => { test("GIVEN image tag is not found, EXPECT empty array returned", async () => {
fetchMock.mockResolvedValue({ fetchMock.mockResolvedValue({
body: "<html><body></body></html>", body: "<html><body></body></html>",
errored: undefined, errored: undefined,
@ -61,10 +62,10 @@ describe("FetchImageFromRedditGallery", () => {
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image"); const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined(); expect(result.length).toBe(0);
}); });
test("GIVEN image source attribute is not found, EXPECT undefined returned", async () => { test("GIVEN image source attribute is not found, EXPECT empty array returned", async () => {
fetchMock.mockResolvedValue({ fetchMock.mockResolvedValue({
body: "<html><body><img /></body></html>", body: "<html><body><img /></body></html>",
errored: undefined, errored: undefined,
@ -73,10 +74,10 @@ describe("FetchImageFromRedditGallery", () => {
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image"); const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined(); expect(result.length).toBe(0);
}); });
test("GIVEN image source attribute is not found that is a preview.redd.it url, EXPECT undefined returned", async () => { test("GIVEN image source attribute is not found that is a preview.redd.it url, EXPECT empty array returned", async () => {
fetchMock.mockResolvedValue({ fetchMock.mockResolvedValue({
body: "<html><body><img src='main.png' /></body></html>", body: "<html><body><img src='main.png' /></body></html>",
errored: undefined, errored: undefined,
@ -85,6 +86,6 @@ describe("FetchImageFromRedditGallery", () => {
const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image"); const result = await ImageHelper.FetchImageFromRedditGallery("https://redd.it/gallery/image");
expect(result).toBeUndefined(); expect(result.length).toBe(0);
}); });
}); });

View file

@ -23,6 +23,7 @@ describe("GenerateOutput", () => {
Title: "This is my Ms Bear!", Title: "This is my Ms Bear!",
Ups: 17, Ups: 17,
Url: "https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d", Url: "https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d",
Gallery: ["https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d"],
}, },
} as IReturnResult; } as IReturnResult;
@ -55,6 +56,7 @@ describe("GenerateOutput", () => {
Title: "This is my Ms Bear!", Title: "This is my Ms Bear!",
Ups: 17, Ups: 17,
Url: "https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d", Url: "https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d",
Gallery: ["https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d"],
}, },
} as IReturnResult; } as IReturnResult;
@ -89,6 +91,7 @@ describe("GenerateOutput", () => {
Title: "This is my Ms Bear!", Title: "This is my Ms Bear!",
Ups: 17, Ups: 17,
Url: "https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d", Url: "https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d",
Gallery: ["https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d"],
}, },
} as IReturnResult; } as IReturnResult;
@ -102,4 +105,40 @@ describe("GenerateOutput", () => {
// Assert // Assert
expect(result).toMatchSnapshot(); expect(result).toMatchSnapshot();
}); });
test("GIVEN the Gallery input has more than 1 item, EXPECT Gallery line to be added", () => {
// Arrange
const response = {
IsSuccess: true,
Query: {
subreddit: "rabbits",
sortBy: "hot",
limit: 100,
},
Result: {
Archived: false,
Author: 'author',
Downs: 0,
Hidden: false,
Permalink: "/r/Rabbits/comments/1dj8pbt/this_is_my_ms_bear/",
Subreddit: "Rabbits",
SubredditSubscribers: 654751,
Title: "This is my Ms Bear!",
Ups: 17,
Url: "https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d",
Gallery: [
"https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d",
"https://preview.redd.it/d5yno653zf7d1.jpg?width=640&crop=smart&auto=webp&s=5064d1caec3c12ac2855eb57ff131d0b313d5e9d"
],
},
} as IReturnResult;
const options = {} as ICliOptions;
// Act
const result = OutputHelper.GenerateOutput(response, options);
// Assert
expect(result).toMatchSnapshot();
});
}); });