Skip to content

Commit

Permalink
feat: replace some instances of manual avatar fetching for projects (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
MiniDigger committed Aug 18, 2024
1 parent eeb74db commit bd4ca23
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class AvatarService extends HangarComponent {
public static final String USER = "user";
public static final String PROJECT = "project";

private static AvatarService instance;

private final FileService fileService;
private final ImageService imageService;
private final AvatarDAO avatarDAO;
Expand Down Expand Up @@ -71,12 +73,21 @@ public void setupDefault() {
}
this.defaultAvatarUrl = this.fileService.getAvatarUrl("default", "default", "0");
logger.info("Default avatar url is {}", this.defaultAvatarUrl);
instance = this;
}

public static AvatarService getInstance() {
return instance;
}

public String getDefaultAvatarUrl() {
return this.defaultAvatarUrl;
}

public String getAvatarUrlPrefix() {
return this.fileService.getAvatarUrlPrefix();
}

/*
* Get methods
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ public interface HangarProjectsDAO {
" p.keywords," +
" p.donation_enabled," +
" p.donation_subject," +
" p.sponsors" +
" p.sponsors," +
" hp.avatar," +
" hp.avatar_fallback" +
" FROM home_projects hp" +
" JOIN projects_extra p ON hp.id = p.id" +
" JOIN users u ON p.owner_id = u.id" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ public interface ProjectsApiDAO {
" p.keywords," +
" p.donation_enabled," +
" p.donation_subject," +
" p.sponsors" +
" p.sponsors," +
" hp.avatar," +
" hp.avatar_fallback" +
" FROM home_projects hp" +
" JOIN projects_extra p ON hp.id = p.id" +
" WHERE lower(p.slug) = lower(:slug)" +
Expand Down Expand Up @@ -99,6 +101,8 @@ public interface ProjectsApiDAO {
hp.sponsors,
hp.last_updated,
hp.supported_platforms,
hp.avatar,
hp.avatar_fallback,
((extract(EPOCH FROM hp.last_updated) - 1609459200) / 604800) * 1 AS last_updated_double,-- for ordering --
exists(SELECT 1 FROM project_stars ps WHERE ps.project_id = hp.id AND ps.user_id = :requesterId) AS starred,
exists(SELECT 1 FROM project_watchers pw WHERE pw.project_id = hp.id AND pw.user_id = :requesterId) AS watching,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ public interface UsersApiDAO {
hp.watchers,
hp.category,
hp.last_updated,
hp.visibility
hp.visibility,
hp.avatar,
hp.avatar_fallback
FROM users u
JOIN project_stars ps ON u.id = ps.user_id
JOIN home_projects hp ON ps.project_id = hp.id
Expand Down Expand Up @@ -75,7 +77,9 @@ SELECT count(*)
hp.watchers,
hp.category,
hp.last_updated,
hp.visibility
hp.visibility,
hp.avatar,
hp.avatar_fallback
FROM users u
JOIN project_watchers pw ON u.id = pw.user_id
JOIN home_projects hp ON pw.project_id = hp.id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.papermc.hangar.model.api.project.settings.ProjectSettings;
import io.papermc.hangar.model.common.projects.Category;
import io.papermc.hangar.model.common.projects.Visibility;
import io.papermc.hangar.util.AvatarUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.OffsetDateTime;
import org.jdbi.v3.core.enums.EnumByOrdinal;
Expand All @@ -19,18 +20,20 @@ public class Project extends ProjectCompact {
private final ProjectSettings settings;

@JdbiConstructor
public Project(final OffsetDateTime createdAt, final long id, final String name, @Nested final ProjectNamespace namespace, @Nested final ProjectStats stats, @EnumByOrdinal final Category category, final String description, final OffsetDateTime lastUpdated, @EnumByOrdinal final Visibility visibility, @Nested final UserActions userActions, @Nested final ProjectSettings settings) {
public Project(final OffsetDateTime createdAt, final long id, final String name, @Nested final ProjectNamespace namespace, @Nested final ProjectStats stats, @EnumByOrdinal final Category category, final String description, final OffsetDateTime lastUpdated, @EnumByOrdinal final Visibility visibility, @Nested final UserActions userActions, @Nested final ProjectSettings settings, final String avatar, final String avatarFallback) {
super(createdAt, id, name, namespace, stats, category, lastUpdated, visibility);
this.description = description;
this.userActions = userActions;
this.settings = settings;
this.setAvatarUrl(AvatarUtil.avatarUrl(avatar, avatarFallback));
}

public Project(final Project other) {
super(other.createdAt, other.id, other.name, other.namespace, other.stats, other.category, other.lastUpdated, other.visibility);
this.description = other.description;
this.userActions = other.userActions;
this.settings = other.settings;
this.avatarUrl = other.avatarUrl;
}

public String getDescription() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@ public class ProjectsApiService extends HangarComponent {

private final ProjectsApiDAO projectsApiDAO;
private final UsersApiService usersApiService;
private final AvatarService avatarService;

@Autowired
public ProjectsApiService(final ProjectsApiDAO projectsApiDAO, final UsersApiService usersApiService, final AvatarService avatarService) {
public ProjectsApiService(final ProjectsApiDAO projectsApiDAO, final UsersApiService usersApiService) {
this.projectsApiDAO = projectsApiDAO;
this.usersApiService = usersApiService;
this.avatarService = avatarService;
}

public Project getProject(final String slug) {
Expand All @@ -47,8 +45,6 @@ public Project getProject(final String slug) {
if (project == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Project " + slug + " not found");
}
// TODO rewrite avatar fetching
project.setAvatarUrl(this.avatarService.getProjectAvatarUrl(project.getId(), project.getNamespace().getOwner()));
return project;
}

Expand Down Expand Up @@ -109,10 +105,6 @@ public PaginatedResult<Project> getProjects(final RequestPagination pagination,

final Long userId = this.getHangarUserId();
final List<Project> projects = this.projectsApiDAO.getProjects(seeHidden, userId, pagination, query);
for (final Project project : projects) {
// TODO rewrite avatar fetching
project.setAvatarUrl(this.avatarService.getProjectAvatarUrl(project.getId(), project.getNamespace().getOwner()));
}
return new PaginatedResult<>(new Pagination(this.projectsApiDAO.countProjects(seeHidden, userId, pagination), pagination), projects);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ public PaginatedResult<ProjectCompact> getUserStarred(final String userName, fin
final boolean canSeeHidden = this.getGlobalPermissions().has(Permission.SeeHidden);
final Long userId = this.getHangarUserId();
final List<ProjectCompact> projects = this.usersApiDAO.getUserStarred(userName, canSeeHidden, userId, pagination);
// TODO rewrite avatar fetching
projects.forEach(p -> p.setAvatarUrl(this.avatarService.getProjectAvatarUrl(p.getId(), p.getNamespace().getOwner())));
final long count = this.usersApiDAO.getUserStarredCount(userName, canSeeHidden, userId);
return new PaginatedResult<>(new Pagination(count, pagination), projects);
}
Expand All @@ -109,8 +107,6 @@ public PaginatedResult<ProjectCompact> getUserWatching(final String userName, f
final boolean canSeeHidden = this.getGlobalPermissions().has(Permission.SeeHidden);
final Long userId = this.getHangarUserId();
final List<ProjectCompact> projects = this.usersApiDAO.getUserWatching(userName, canSeeHidden, userId, pagination);
// TODO rewrite avatar fetching
projects.forEach(p -> p.setAvatarUrl(this.avatarService.getProjectAvatarUrl(p.getId(), p.getNamespace().getOwner())));
final long count = this.usersApiDAO.getUserWatchingCount(userName, canSeeHidden, userId);
return new PaginatedResult<>(new Pagination(count, pagination), projects);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@ default void moveFile(String oldPath, String newPath) throws IOException {

String getVersionDownloadUrl(String user, String project, String version, Platform platform, String fileName);

String getAvatarUrl(String type, String subject, String version);
default String getAvatarUrl(String type, String subject, String version) {
return getAvatarUrlPrefix() + "/" + type + "/" + subject + ".webp?v=" + version;
}

String getAvatarUrlPrefix();
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public String getVersionDownloadUrl(final String user, final String project, fin
}

@Override
public String getAvatarUrl(final String type, final String subject, final String version) {
return this.hangarConfig.getBaseUrl() + "/api/internal/avatar/" + type + "/" + subject + ".webp?v=" + version;
public String getAvatarUrlPrefix() {
return this.hangarConfig.getBaseUrl() + "/api/internal/avatar";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public String getVersionDownloadUrl(final String user, final String project, fin
}

@Override
public String getAvatarUrl(final String type, final String subject, final String version) {
return this.config.cdnEndpoint() + (this.config.cdnIncludeBucket() ? "/" + this.config.bucket() : "") + "/avatars/" + type + "/" + subject + ".webp?v=" + version;
public String getAvatarUrlPrefix() {
return this.config.cdnEndpoint() + (this.config.cdnIncludeBucket() ? "/" + this.config.bucket() : "") + "/avatars";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,9 @@ public HangarProject getHangarProject(final String slug) {
final Map<Long, HangarProjectPage> pages = this.projectPageService.getProjectPages(projectId);
final CompletableFuture<List<HangarProject.PinnedVersion>> pinnedVersions = this.supply(() -> this.pinnedVersionService.getPinnedVersions(ownerName, project.getNamespace().getSlug(), projectId));
final ExtendedProjectPage projectPage = this.projectPageService.getProjectHomePage(projectId);
// TODO rewrite avatar fetching
final String avatarUrl = this.avatarService.getProjectAvatarUrl(project.getId(), project.getNamespace().getOwner());

mainChannelFuture.join();
final HangarProject hangarProject = new HangarProject(
return new HangarProject(
project,
membersFuture.join(),
lastVisibilityChangeComment,
Expand All @@ -185,8 +183,6 @@ public HangarProject getHangarProject(final String slug) {
mainChannelVersions,
projectPage
);
hangarProject.setAvatarUrl(avatarUrl);
return hangarProject;
}

private <T> CompletableFuture<T> supply(final Supplier<T> supplier) {
Expand Down
23 changes: 23 additions & 0 deletions backend/src/main/java/io/papermc/hangar/util/AvatarUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.papermc.hangar.util;


import io.papermc.hangar.components.images.service.AvatarService;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

public final class AvatarUtil {

@NonNull
@SuppressWarnings("ReplaceNullCheck")
public static String avatarUrl(@Nullable String avatar, @Nullable String fallback) {
String prefix = AvatarService.getInstance().getAvatarUrlPrefix();

if (avatar != null) {
return prefix + avatar;
} else if (fallback != null) {
return prefix + fallback;
} else {
return AvatarService.getInstance().getDefaultAvatarUrl();
}
}
}
30 changes: 19 additions & 11 deletions backend/src/main/resources/db/migration/R__02_home_view.sql
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,28 @@ CREATE MATERIALIZED VIEW home_projects AS
JOIN project_versions pv ON pvpd.version_id = pv.id
GROUP BY pv.project_id, v.platform)
SELECT p.*,
array_agg(DISTINCT pm.user_id) AS project_members,
array_agg(DISTINCT lower(u.name)) AS project_member_names,
coalesce(pva.views::bigint, 0::bigint) AS views,
coalesce(pda.downloads::bigint, 0::bigint) AS downloads,
coalesce(pvr.recent_views::bigint, 0::bigint) AS recent_views,
coalesce(pdr.recent_downloads::bigint, 0::bigint) AS recent_downloads,
coalesce(ps.stars::bigint, 0::bigint) AS stars,
coalesce(pw.watchers::bigint, 0::bigint) AS watchers,
coalesce(max(lv.created_at), p.created_at) AS last_updated,
array_agg(DISTINCT pm.user_id) AS project_members,
array_agg(DISTINCT lower(u.name)) AS project_member_names,
coalesce(pva.views::bigint, 0::bigint) AS views,
coalesce(pda.downloads::bigint, 0::bigint) AS downloads,
coalesce(pvr.recent_views::bigint, 0::bigint) AS recent_views,
coalesce(pdr.recent_downloads::bigint, 0::bigint) AS recent_downloads,
coalesce(ps.stars::bigint, 0::bigint) AS stars,
coalesce(pw.watchers::bigint, 0::bigint) AS watchers,
coalesce(max(lv.created_at), p.created_at) AS last_updated,
/* avatar stuff */
(SELECT '/project/' || p.id || '.webp?v=' || a.version
FROM avatars a
WHERE a.type = 'project' AND a.subject = p.id::text) AS avatar,
(SELECT '/user/' || o.uuid::text || '.webp?v=' || a.version
FROM avatars a
JOIN users o ON a.subject = o.uuid::text
WHERE o.id = p.owner_id AND a.type = 'user' AND a.subject = o.uuid::text) AS avatar_fallback,
/* store the supported platforms and versions */
/* format: [{"platform": 0, "versions": ["1.19.4"]}, {"platform": 1, "versions": ["1.18"]}, {"platform": 2, "versions": ["3.2"]}] */
(SELECT jsonb_agg(jsonb_build_object('platform', pva.platform, 'versions', pva.versions))
FROM platform_versions_agg pva
WHERE pva.project_id = p.id) AS supported_platforms,
WHERE pva.project_id = p.id) AS supported_platforms,
/* search stuff
we want to search in the name, description, keywords and owner_name, in that priority
for name and owner name we search the original name and a snake_case version so tsvector can find submatches
Expand All @@ -68,7 +76,7 @@ CREATE MATERIALIZED VIEW home_projects AS
to_tsvector('english'::regconfig, regexp_replace(p.owner_name::text, '([a-z])([A-Z]+)'::text, '\1_\2'::text, 'g'::text))
), 'D'::"char"
)
) AS search_words
) AS search_words
FROM projects p
LEFT JOIN project_versions lv ON p.id = lv.project_id
JOIN project_members_all pm ON p.id = pm.id
Expand Down

0 comments on commit bd4ca23

Please sign in to comment.