GitRoot
craft your forge, build your project, grow your community freely
1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
2//
3// SPDX-License-Identifier: EUPL-1.2
4
5import { JSON } from "json-as";
6import {
7 Commit,
8 File,
9 Plugin,
10 PluginRun,
11 pluginRunWhenAll,
12 PluginWrite,
13 PluginWriteRight,
14 PluginWriteRightCanAdd,
15 PluginWriteRightCanMod,
16 Register,
17 Server,
18} from "plugin/server";
19
20export * from "plugin/exports";
21
22@json
23class FluxConf {
24 constructor(
25 public link: string,
26 public path: string,
27 public title: string,
28 public description: string,
29 public language: string,
30 ) {}
31
32 static build(
33 link: string,
34 path: string,
35 title: string,
36 description: string,
37 language: string,
38 ): FluxConf {
39 return new FluxConf(link, path, title, description, language);
40 }
41
42 generateEmptyRss(): string {
43 return `<rss version="2.0">
44 <channel>
45 <title>${this.title}</title>
46 <link>${this.link}</link>
47 <description>${this.description}</description>
48 <language>${this.language}</language>
49 <generator>Pollen plugin - GitRoot</generator>
50 <!-- next -->
51 </channel>
52</rss>`;
53 }
54}
55
56@json
57class Conf {
58 flux: Array<FluxConf> = [
59 FluxConf.build(
60 "https://YOURINSTANCE.com/YOURPROJECT/",
61 "rss/all.xml",
62 "All push",
63 "Every push made in your forge",
64 "en",
65 ),
66 ];
67
68 static default(): JSON.Raw {
69 return JSON.Raw.from(JSON.stringify<Conf>(new Conf()));
70 }
71}
72
73const defaultRun: PluginRun = PluginRun.build(
74 "**/*",
75 ["*"],
76 pluginRunWhenAll,
77 [],
78 PluginWrite.build(
79 [],
80 [
81 PluginWriteRight.build("rss/*", [
82 PluginWriteRightCanAdd,
83 PluginWriteRightCanMod,
84 ]),
85 ],
86 [],
87 [],
88 ),
89 Conf.default(),
90);
91
92function generateItem(conf: FluxConf, commits: Array<Commit>): string {
93 const before = `<item><author>${commits[0].committerEmail} (${commits[0].committerName})</author><link>${conf.link}</link><title>Has pushed ${commits.length} commits on ${commits[0].branch}</title><description>`;
94 const beforeDesc = `<![CDATA[<p>All commits:</p><ul>`;
95 const afterDesc = `</ul>]]>`;
96 const after = `</description><pubDate>${commits[0].date.toUTCString()}</pubDate><guid>${
97 commits[0].hash
98 }</guid></item>`;
99 const html =
100 beforeDesc +
101 commits
102 .sort((a, b) => a.date.getUTCMilliseconds() - b.date.getUTCMilliseconds())
103 .reduce((acc, item) => {
104 return `${acc}<li>${item.message.replaceAll("\n", "<br/>")}</li>`;
105 }, "") +
106 afterDesc;
107 return before + html + after;
108}
109
110class Pollen implements Plugin {
111 private server: Server;
112 private conf: Conf | null = null;
113 private commits: Array<Commit> = new Array<Commit>();
114
115 constructor(server: Server) {
116 this.server = server;
117 }
118
119 init(
120 repoName: string,
121 confHasChanged: boolean,
122 serializedConf: string,
123 ): void {
124 this.conf = JSON.parse<Conf>(serializedConf);
125
126 for (let i = 0; i < this.conf!.flux.length; ++i) {
127 const flux = this.conf!.flux[i];
128 if (!this.server.webcontent().exists(flux.path)) {
129 this.server.modifyWebContent(flux.path, flux.generateEmptyRss());
130 }
131 }
132 return;
133 }
134
135 startCommit(commit: Commit): void {
136 this.commits.push(commit);
137 return;
138 }
139
140 addFile(file: File): void {
141 return;
142 }
143
144 modFile(file: File): void {
145 return;
146 }
147
148 delFile(file: File): void {
149 return;
150 }
151
152 endCommit(commit: Commit): void {
153 return;
154 }
155
156 finish(): void {
157 if (this.conf != null && this.commits.length > 0) {
158 for (let i = 0; i < this.conf!.flux.length; i++) {
159 this.server
160 .webcontent()
161 .replaceContent(
162 this.conf!.flux[i].path,
163 "<!-- next -->",
164 "<!-- next -->\n" + generateItem(this.conf!.flux[i], this.commits),
165 );
166 }
167 }
168 this.conf = null;
169 this.commits = [];
170 return;
171 }
172}
173
174function build(server: Server): Plugin {
175 return new Pollen(server);
176}
177
178export function install(): void {
179 Register([defaultRun], build);
180}