feat: implement developer collaboration hub with telegram/discord interactive UI

This commit is contained in:
Shanmuga Krishnan S M
2026-07-29 08:27:46 +05:30
parent 2b4a8ee0e9
commit 8bd0718b72
13 changed files with 1625 additions and 129 deletions

View File

@@ -0,0 +1,103 @@
package com.rit.portal.controller;
import com.rit.portal.entity.CollabApplication;
import com.rit.portal.entity.CollabRequest;
import com.rit.portal.repository.CollabApplicationRepository;
import com.rit.portal.repository.CollabRequestRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/collab")
public class CollabController {
@Autowired
private CollabRequestRepository collabRequestRepository;
@Autowired
private CollabApplicationRepository collabApplicationRepository;
private final RestTemplate restTemplate = new RestTemplate();
private static final String BOT_COLLAB_APP_URL = "http://localhost:8082/send_collab_application";
@GetMapping
public List<CollabRequest> getAllCollabRequests() {
return collabRequestRepository.findAllByOrderByCreatedAtDesc();
}
@GetMapping("/{id}")
public ResponseEntity<CollabRequest> getCollabRequestById(@PathVariable Integer id) {
return collabRequestRepository.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public CollabRequest createCollabRequest(@RequestBody CollabRequest request) {
if (request.getStatus() == null) request.setStatus("OPEN");
if (request.getApplicationsCount() == null) request.setApplicationsCount(0);
request.setCreatedAt(LocalDateTime.now());
return collabRequestRepository.save(request);
}
@PostMapping("/{id}/apply")
public ResponseEntity<CollabApplication> applyToCollabRequest(
@PathVariable Integer id,
@RequestBody CollabApplication application) {
return collabRequestRepository.findById(id).map(request -> {
application.setCollabRequest(request);
if (application.getStatus() == null) application.setStatus("PENDING");
application.setCreatedAt(LocalDateTime.now());
CollabApplication savedApp = collabApplicationRepository.save(application);
// Increment count on parent request
request.setApplicationsCount(request.getApplicationsCount() + 1);
collabRequestRepository.save(request);
// Notify Telegram/Discord intermediary bot asynchronously
new Thread(() -> {
try {
Map<String, Object> payload = new HashMap<>();
payload.put("collab_id", request.getId());
payload.put("application_id", savedApp.getId());
payload.put("project_idea", request.getProjectIdea());
payload.put("tag", request.getTag());
payload.put("author_name", request.getAuthorName());
payload.put("contact_info", request.getContactInfo());
payload.put("telegram_chat_id", request.getTelegramChatId());
payload.put("discord_user_id", request.getDiscordUserId());
payload.put("applicant_name", savedApp.getApplicantName());
payload.put("applicant_dept", savedApp.getApplicantDept());
payload.put("applicant_year", savedApp.getApplicantYear());
payload.put("applicant_contact", savedApp.getApplicantContact());
payload.put("message", savedApp.getMessage());
restTemplate.postForEntity(BOT_COLLAB_APP_URL, payload, String.class);
} catch (Exception e) {
System.err.println("Failed to send collab application notification to bot: " + e.getMessage());
}
}).start();
return ResponseEntity.ok(savedApp);
}).orElse(ResponseEntity.notFound().build());
}
@PutMapping("/applications/{applicationId}/status")
public ResponseEntity<CollabApplication> updateApplicationStatus(
@PathVariable Integer applicationId,
@RequestParam String status) {
return collabApplicationRepository.findById(applicationId).map(app -> {
app.setStatus(status.toUpperCase());
CollabApplication updated = collabApplicationRepository.save(app);
return ResponseEntity.ok(updated);
}).orElse(ResponseEntity.notFound().build());
}
}

View File

@@ -0,0 +1,48 @@
package com.rit.portal.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.*;
import java.time.LocalDateTime;
@Entity
@Table(name = "collab_applications")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CollabApplication {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "collab_request_id", nullable = false)
@JsonIgnore
private CollabRequest collabRequest;
@Column(name = "applicant_name", nullable = false)
private String applicantName;
@Column(name = "applicant_dept", nullable = false)
private String applicantDept;
@Column(name = "applicant_year", nullable = false)
private String applicantYear;
@Column(name = "applicant_contact", nullable = false)
private String applicantContact;
@Column(columnDefinition = "TEXT")
private String message;
@Column(name = "status")
@Builder.Default
private String status = "PENDING";
@Column(name = "created_at")
@Builder.Default
private LocalDateTime createdAt = LocalDateTime.now();
}

View File

@@ -0,0 +1,64 @@
package com.rit.portal.entity;
import jakarta.persistence.*;
import lombok.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "collab_requests")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CollabRequest {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "author_name", nullable = false)
private String authorName;
@Column(nullable = false)
private String department;
@Column(nullable = false)
private String year;
@Column(name = "project_idea", nullable = false, columnDefinition = "TEXT")
private String projectIdea;
@Column(name = "github_link")
private String githubLink;
@Column(nullable = false)
private String tag;
@Column(name = "contact_info")
private String contactInfo;
@Column(name = "telegram_chat_id")
private Long telegramChatId;
@Column(name = "discord_user_id")
private String discordUserId;
@Column(name = "status")
@Builder.Default
private String status = "OPEN";
@Column(name = "applications_count")
@Builder.Default
private Integer applicationsCount = 0;
@Column(name = "created_at")
@Builder.Default
private LocalDateTime createdAt = LocalDateTime.now();
@OneToMany(mappedBy = "collabRequest", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@Builder.Default
private List<CollabApplication> applications = new ArrayList<>();
}

View File

@@ -0,0 +1,9 @@
package com.rit.portal.repository;
import com.rit.portal.entity.CollabApplication;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CollabApplicationRepository extends JpaRepository<CollabApplication, Integer> {
}

View File

@@ -0,0 +1,11 @@
package com.rit.portal.repository;
import com.rit.portal.entity.CollabRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CollabRequestRepository extends JpaRepository<CollabRequest, Integer> {
List<CollabRequest> findAllByOrderByCreatedAtDesc();
}