Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package io.paradaux.api.controllers;

import io.paradaux.api.models.VisitCountEntry;
import io.paradaux.api.models.VisitEntry;
import io.paradaux.api.models.annotations.ProtectedRoute;
import io.paradaux.api.services.VisitsService;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/analytics/visits")
public class VisitsController {
Expand All @@ -25,4 +28,9 @@ public void insertVisit(@RequestBody VisitEntry visit) {
public Integer getVisitCountByProject(@PathVariable String project) {
return visitsService.getVisitCount(project);
}

@GetMapping("/projects")
public List<VisitCountEntry> getVisitCountsForProjects() {
return visitsService.getVisitCountsForProjects();
}
}
4 changes: 4 additions & 0 deletions src/main/java/io/paradaux/api/mappers/VisitsMapper.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package io.paradaux.api.mappers;

import io.paradaux.api.models.VisitCountEntry;
import io.paradaux.api.models.VisitEntry;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface VisitsMapper {
void insertVisit(VisitEntry visit);
Integer getVisitCount(String project);
List<VisitCountEntry> getVisitCountsForProjects();
void refreshVisitCache();
}
16 changes: 16 additions & 0 deletions src/main/java/io/paradaux/api/models/VisitCountEntry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.paradaux.api.models;

import lombok.Data;

import java.io.Serial;
import java.io.Serializable;

@Data
public class VisitCountEntry implements Serializable {

@Serial
private static final long serialVersionUID = 1L;

private String project;
private int totalCount;
}
10 changes: 10 additions & 0 deletions src/main/java/io/paradaux/api/services/VisitsService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package io.paradaux.api.services;

import io.paradaux.api.models.VisitCountEntry;
import io.paradaux.api.models.VisitEntry;

import java.util.List;

public interface VisitsService {
/**
* Inserts a new IfumVisit record into the database.
Expand All @@ -15,6 +18,13 @@ public interface VisitsService {
*/
Integer getVisitCount(String project);

/**
* Retrieves a list of visit counts grouped by project.
*
* @return a list of VisitCountEntry objects containing project names and their visit counts
*/
List<VisitCountEntry> getVisitCountsForProjects();

/**
* Refreshes the visit view which groups visit counts by project.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.paradaux.api.services.impl;

import io.paradaux.api.mappers.VisitsMapper;
import io.paradaux.api.models.VisitCountEntry;
import io.paradaux.api.models.VisitEntry;
import io.paradaux.api.services.VisitsService;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -9,6 +10,7 @@
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.TreeSet;

Expand All @@ -18,9 +20,9 @@ public class VisitsServiceImpl implements VisitsService {

private static final TreeSet<String> IGNORED_USER_AGENTS = new TreeSet<>(Arrays.asList(
"bot", "crawler", "spider", "scanner", "curl", "wget",
"python", "java", "php", "unknown", "discord", "(compatible)",
"python", "java", "php", "unknown", "discord", "(compatible;",
"zgrab", "scrapy", "censys", "okhttp", "axios", "go-http-client",
"google", "bing", "yahoo"
"google", "bing", "yahoo", "WhatCMS"
));

private final VisitsMapper visitsMapper;
Expand Down Expand Up @@ -52,6 +54,11 @@ public Integer getVisitCount(String project) {
return visitsMapper.getVisitCount(project);
}

@Override
public List<VisitCountEntry> getVisitCountsForProjects() {
return visitsMapper.getVisitCountsForProjects();
}

@CacheEvict(value = "visitCounts", allEntries = true)
@Override
public void refreshVisitCache() {
Expand Down
9 changes: 9 additions & 0 deletions src/main/resources/mappers/VisitsMapper.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
SELECT total_count FROM analytics.visit_count_view WHERE project = #{project}
</select>

<resultMap id="visitCountResultMap" type="io.paradaux.api.models.VisitCountEntry">
<result property="totalCount" column="total_count" />
<result property="project" column="project" />
</resultMap>

<select id="getVisitCountsForProjects" resultMap="visitCountResultMap">
SELECT total_count, project FROM analytics.visit_count_view;
</select>

<update id="refreshVisitCache" flushCache="true">
REFRESH MATERIALIZED VIEW CONCURRENTLY analytics.visit_count_view;
</update>
Expand Down