Skip to content

Commit 106ffff

Browse files
committed
Add non-modrinth submissions
Closes #5
1 parent cad62ef commit 106ffff

File tree

6 files changed

+178
-22
lines changed

6 files changed

+178
-22
lines changed

botfest/src/main/kotlin/net/modfest/botfest/Platform.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import net.modfest.platform.pojo.PlatformErrorResponse
2020
import net.modfest.platform.pojo.SubmissionData
2121
import net.modfest.platform.pojo.SubmissionPatchData
2222
import net.modfest.platform.pojo.SubmitRequestModrinth
23+
import net.modfest.platform.pojo.SubmitRequestOther
2324
import net.modfest.platform.pojo.UserCreateData
2425
import net.modfest.platform.pojo.UserData
2526
import net.modfest.platform.pojo.UserPatchData
@@ -175,6 +176,13 @@ class PlatformAuthenticated(var client: HttpClient, var discordUser: Snowflake)
175176
}.unwrapErrors().body()
176177
}
177178

179+
suspend fun submitOther(eventId: String, data: SubmitRequestOther): SubmissionData {
180+
return client.post("/event/$eventId/submissions?type=other") {
181+
addAuth()
182+
setBody(data)
183+
}.unwrapErrors().body()
184+
}
185+
178186
suspend fun editSubmissionData(eventId: String, subId: String, edit: SubmissionPatchData) {
179187
client.patch("/event/$eventId/submission/$subId") {
180188
addAuth()

botfest/src/main/kotlin/net/modfest/botfest/extensions/EventCommands.kt

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import dev.kordex.modules.dev.unsafe.extensions.unsafeSlashCommand
1616
import net.modfest.botfest.MAIN_GUILD_ID
1717
import net.modfest.botfest.Platform
1818
import net.modfest.botfest.i18n.Translations
19+
import net.modfest.platform.pojo.SubmitRequestOther
1920
import net.modfest.platform.pojo.UserCreateData
2021
import org.koin.core.component.inject
2122
import java.util.*
@@ -161,10 +162,12 @@ class EventCommands : Extension(), KordExKoinComponent {
161162
}
162163

163164

165+
// commands for submitting
164166
group(Translations.Commands.Event.Submit.name) {
165167
description = Translations.Commands.Event.Submit.description
166-
// command for submitting a mod
167-
ephemeralSubCommand(::SubmitModrinthModal) {
168+
169+
// Submitting a modrinth project
170+
ephemeralSubCommand(::SubmitModalModrinth) {
168171
name = Translations.Commands.Event.Submit.Modrinth.name
169172
description = Translations.Commands.Event.Submit.Modrinth.description
170173

@@ -209,6 +212,45 @@ class EventCommands : Extension(), KordExKoinComponent {
209212
}
210213
}
211214
}
215+
216+
// Submitting a non-modrinth project
217+
ephemeralSubCommand(::SubmitModalOther) {
218+
name = Translations.Commands.Event.Submit.Other.name
219+
description = Translations.Commands.Event.Submit.Other.description
220+
221+
action { modal ->
222+
if (modal == null) return@action
223+
val curEvent = platform.getCurrentEvent().event
224+
225+
if (curEvent == null) {
226+
respond {
227+
content = Translations.Commands.Event.Submit.Response.unavailable
228+
.withContext(this@action)
229+
.translateNamed()
230+
}
231+
return@action
232+
}
233+
234+
val submission = platform.withAuth(this.user).submitOther(curEvent, SubmitRequestOther(
235+
modal.name.value!!,
236+
modal.description.value!!,
237+
setOf("dc:"+user.id),
238+
modal.homepage.value.convertBlankToNull(),
239+
modal.sourcecode.value.convertBlankToNull(),
240+
modal.downloadUrl.value.convertBlankToNull()
241+
))
242+
val eventInfo = platform.getEvent(curEvent)
243+
244+
respond {
245+
content = Translations.Commands.Event.Submit.Response.success
246+
.withContext(this@action)
247+
.translateNamed(
248+
"event" to eventInfo.name,
249+
"mod" to submission.name
250+
)
251+
}
252+
}
253+
}
212254
}
213255
}
214256
}
@@ -243,7 +285,7 @@ class EventCommands : Extension(), KordExKoinComponent {
243285

244286

245287

246-
class SubmitModrinthModal : ModalForm() {
288+
class SubmitModalModrinth : ModalForm() {
247289
override var title: Key = Translations.Modal.Submit.title
248290

249291
val modrinthUrl = lineText {
@@ -254,4 +296,49 @@ class EventCommands : Extension(), KordExKoinComponent {
254296
required = true
255297
}
256298
}
299+
300+
class SubmitModalOther : ModalForm() {
301+
override var title: Key = Translations.Modal.Submit.title
302+
303+
val name = lineText {
304+
label = Translations.Modal.Submission.Name.label
305+
placeholder = Translations.Modal.Submission.Name.placeholder
306+
minLength = 1
307+
maxLength = 128
308+
required = true
309+
}
310+
311+
val description = lineText {
312+
label = Translations.Modal.Submission.Description.label
313+
placeholder = Translations.Modal.Submission.Description.placeholder
314+
minLength = 1
315+
maxLength = 256
316+
required = true
317+
}
318+
319+
val homepage = lineText {
320+
label = Translations.Modal.Submission.Homepage.label
321+
placeholder = Translations.Modal.Submission.Homepage.placeholder
322+
maxLength = 128
323+
required = false
324+
}
325+
326+
val sourcecode = lineText {
327+
label = Translations.Modal.Submission.Source.extendedlabel
328+
placeholder = Translations.Modal.Submission.Source.placeholder
329+
maxLength = 128
330+
required = false
331+
}
332+
333+
val downloadUrl = lineText {
334+
label = Translations.Modal.Submission.Downloadurl.label
335+
placeholder = Translations.Modal.Submission.Downloadurl.placeholder
336+
maxLength = 128
337+
required = false
338+
}
339+
}
340+
}
341+
342+
private fun String?.convertBlankToNull(): String? {
343+
return if (this.isNullOrBlank()) { null } else { this }
257344
}

botfest/src/main/resources/translations/botfest/strings.properties

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ commands.event.submit.name=submit
5757
commands.event.submit.description=submit a project
5858
commands.event.submit.modrinth.name=modrinth
5959
commands.event.submit.modrinth.description=Submit a modrinth project
60+
commands.event.submit.other.name=other
61+
commands.event.submit.other.description=Submit a project
6062
commands.event.submit.response.invalid=`{url}` is not a valid Modrinth URL
6163
commands.event.submit.response.unavailable=There's no current event happening.
6264
commands.event.submit.response.success=Successfully submitted {mod} to {event} :tada:
@@ -98,13 +100,16 @@ modal.submit.url.label=Enter your project's Modrinth URL
98100
modal.submit.url.placeholder=https://modrinth.com/mod/your-mod
99101
modal.submission.edit.title=Edit your mod's data
100102
modal.submission.name.label=Name
101-
modal.submission.name.placeholder=...
103+
modal.submission.name.placeholder=My mod
102104
modal.submission.description.label=Description
103-
modal.submission.description.placeholder=...
105+
modal.submission.description.placeholder=A mod for doing stuff and things
104106
modal.submission.source.label=Sourcecode link
105-
modal.submission.source.placeholder=...
107+
modal.submission.source.extendedlabel=A link to your source code (if applicable)
108+
modal.submission.source.placeholder=https://github.com/...
106109
modal.submission.homepage.label=Link to your project's homepage
107110
modal.submission.homepage.placeholder=https://mymod.com/
111+
modal.submission.downloadurl.label=A download link (if it should be in the pack)
112+
modal.submission.downloadurl.placeholder=https://github.com/.../.../releases/download/v1.0/mymod.jar
108113

109114
apierror.event_no_exists=An event named {n} doesn't exists
110115
apierror.user_no_exists=A user named {n} doesn't exists

common/src/main/java/net/modfest/platform/pojo/SubmitRequestOther.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
import org.jspecify.annotations.NonNull;
44
import org.jspecify.annotations.Nullable;
55

6+
import java.util.Set;
7+
68
public record SubmitRequestOther(
79
@NonNull String name,
810
@NonNull String description,
11+
@NonNull Set<String> authors,
912
@Nullable String homepage,
1013
@Nullable String sourceUrl,
1114
@Nullable String downloadUrl

platform_api/src/main/java/net/modfest/platform/controller/EventController.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package net.modfest.platform.controller;
22

3-
import net.modfest.platform.pojo.EventData;
4-
import net.modfest.platform.pojo.SubmissionData;
5-
import net.modfest.platform.pojo.SubmissionPatchData;
6-
import net.modfest.platform.pojo.SubmitRequestModrinth;
3+
import net.modfest.platform.pojo.*;
74
import net.modfest.platform.security.PermissionUtils;
85
import net.modfest.platform.security.Permissions;
96
import net.modfest.platform.service.EventService;
@@ -18,6 +15,7 @@
1815

1916
import java.util.Collection;
2017
import java.util.List;
18+
import java.util.stream.Collectors;
2119

2220
@RestController
2321
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@@ -87,9 +85,34 @@ public List<SubmissionData> getSubmissions(@PathVariable String eventId) {
8785
return service.getSubmissionsFromEvent(event).toList();
8886
}
8987

90-
@PostMapping(value = "/event/{eventId}/submissions", params = "type=modrinth")
88+
@PostMapping(value = "/event/{eventId}/submissions", params = "type=other")
9189
@RequiresPermissions(Permissions.Event.SUBMIT)
92-
public SubmissionData makeSubmission(@PathVariable String eventId, @RequestBody SubmitRequestModrinth submission) {
90+
public SubmissionData makeSubmissionOther(@PathVariable String eventId, @RequestBody SubmitRequestOther submission) {
91+
var event = getEvent(eventId);
92+
var subject = SecurityUtils.getSubject();
93+
var bypass = subject.isPermitted(Permissions.Event.SUBMIT_BYPASS);
94+
var can_others = subject.isPermitted(Permissions.Event.SUBMIT_OTHER);
95+
96+
var authors = submission.authors()
97+
.stream()
98+
.map(id -> userController.getSingleUser(id)).collect(Collectors.toSet());
99+
var self = authors.stream().anyMatch(d -> PermissionUtils.owns(subject, d));
100+
101+
if (!event.phase().canSubmit() && !bypass) {
102+
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Event does not accept submissions");
103+
}
104+
105+
if (!self && !can_others) {
106+
throw new ResponseStatusException(HttpStatus.FORBIDDEN,
107+
"You don't have permissions to submit for people other than yourself");
108+
}
109+
110+
return service.makeSubmissionOther(event, authors, submission);
111+
}
112+
113+
@PostMapping(value = "/event/{eventId}/submissions", params = "type=modrinth")
114+
@RequiresPermissions(Permissions.Event.SUBMIT)
115+
public SubmissionData makeSubmissionModrinth(@PathVariable String eventId, @RequestBody SubmitRequestModrinth submission) {
93116
var event = getEvent(eventId);
94117
var subject = SecurityUtils.getSubject();
95118
var bypass = subject.isPermitted(Permissions.Event.SUBMIT_BYPASS);
@@ -111,7 +134,7 @@ public SubmissionData makeSubmission(@PathVariable String eventId, @RequestBody
111134
"You don't have permissions to submit for people other than yourself");
112135
}
113136

114-
return service.makeModrinthSubmission(eventId, submission.modrinthProject());
137+
return service.makeSubmissionModrinth(eventId, submission.modrinthProject());
115138
}
116139

117140
@PatchMapping("/event/{eventId}/submission/{subId}")

platform_api/src/main/java/net/modfest/platform/service/SubmissionService.java

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package net.modfest.platform.service;
22

3-
import net.modfest.platform.pojo.EventData;
4-
import net.modfest.platform.pojo.SubmissionData;
5-
import net.modfest.platform.pojo.SubmissionPatchData;
6-
import net.modfest.platform.pojo.UserData;
3+
import net.modfest.platform.pojo.*;
74
import net.modfest.platform.repository.SubmissionRepository;
85
import nl.theepicblock.dukerinth.ModrinthApi;
96
import nl.theepicblock.dukerinth.VersionFilter;
@@ -15,10 +12,7 @@
1512
import org.springframework.context.annotation.Lazy;
1613
import org.springframework.stereotype.Service;
1714

18-
import java.util.Comparator;
19-
import java.util.List;
20-
import java.util.Objects;
21-
import java.util.Set;
15+
import java.util.*;
2216
import java.util.stream.Collectors;
2317
import java.util.stream.Stream;
2418

@@ -93,7 +87,43 @@ public Stream<UserData> getUsersForRinthProject(String modrinthProjectId) {
9387
.filter(Objects::nonNull);
9488
}
9589

96-
public SubmissionData makeModrinthSubmission(String eventId, String mrProjectId) {
90+
public SubmissionData makeSubmissionOther(EventData event, Set<UserData> authors, SubmitRequestOther submitData) {
91+
var subId = submitData.name()
92+
.toLowerCase(Locale.ROOT)
93+
.replace(" ", "_")
94+
.replaceAll("[^a-z0-9_\\-\\s]", "");
95+
if (subId.isBlank()) {
96+
throw new IllegalStateException();
97+
}
98+
var idKey = new SubmissionRepository.SubmissionId(event.id(), subId);
99+
if (submissionRepository.contains(idKey)) {
100+
// TODO friendlier error message for duplicates
101+
throw new IllegalStateException();
102+
}
103+
var submission = new SubmissionData(
104+
subId,
105+
event.id(),
106+
submitData.name(),
107+
submitData.description(),
108+
authors.stream().map(a -> a.id()).collect(Collectors.toSet()),
109+
new SubmissionData.AssociatedData(
110+
new SubmissionData.AssociatedData.Other(
111+
submitData.homepage(),
112+
submitData.downloadUrl()
113+
)
114+
),
115+
new SubmissionData.Images(null, null),
116+
submitData.sourceUrl(),
117+
new SubmissionData.Awards(
118+
Set.of(),
119+
Set.of()
120+
)
121+
);
122+
submissionRepository.save(submission);
123+
return submission;
124+
}
125+
126+
public SubmissionData makeSubmissionModrinth(String eventId, String mrProjectId) {
97127
var project = modrinth.projects().getProject(mrProjectId);
98128
var subId = project.slug; // Normalize id by using slug. Just in case the user entered an actual id
99129
if (subId == null) subId = project.id;

0 commit comments

Comments
 (0)