tangled
alpha
login
or
join now
pyrox.dev
/
nixpkgs
lol
0
fork
atom
overview
issues
pulls
pipelines
maubot: update plugins
chayleaf
1 year ago
1de3be8a
0cbe9c51
+250
-194
2 changed files
expand all
collapse all
unified
split
pkgs
tools
networking
maubot
plugins
generated.json
update.py
+108
-80
pkgs/tools/networking/maubot/plugins/generated.json
···
66
}
67
},
68
"github": {
69
-
"hash": "sha256-O3FhZ6US4iACEzEKdHLjBZfOJlHNGEeLSrHdqWULFvk=",
70
"owner": "rom4nik",
71
"repo": "maubot-alternatingcaps",
72
-
"rev": "v0.1.2"
73
},
74
"manifest": {
75
"id": "pl.rom4nik.maubot.alternatingcaps",
76
"license": "MIT",
77
"main_class": "AlternatingCaps",
0
78
"modules": [
79
"alternatingcaps"
80
],
81
-
"version": "0.1.2"
82
}
83
},
84
"animemanga": {
···
202
"version": "1.0.0"
203
}
204
},
205
-
"characterai": {
206
-
"attrs": {
207
-
"meta": {
208
-
"changelog": "https://github.com/Matthieu-LAURENT39/maubot-characterai/releases",
209
-
"description": "Chat with characters from [character.ai](https://character.ai/) in your Matrix rooms! Very customizable.",
210
-
"downloadPage": "https://github.com/Matthieu-LAURENT39/maubot-characterai/releases",
211
-
"homepage": "https://github.com/Matthieu-LAURENT39/maubot-characterai"
212
-
}
213
-
},
214
-
"github": {
215
-
"hash": "sha256-nyVz0PDyNGAIFCxakWzEe8AG/PU+HlZJQQ85SL1bEvs=",
216
-
"owner": "Matthieu-LAURENT39",
217
-
"repo": "maubot-characterai",
218
-
"rev": "v0.2.1"
219
-
},
220
-
"manifest": {
221
-
"config": true,
222
-
"database": true,
223
-
"database_type": "asyncpg",
224
-
"dependencies": [
225
-
"characterai"
226
-
],
227
-
"extra_files": [
228
-
"base-config.yaml"
229
-
],
230
-
"id": "com.github.Matthieu-LAURENT39.maubot-characterai",
231
-
"license": "MIT",
232
-
"main_class": "CAIBot",
233
-
"maubot": "0.1.0",
234
-
"modules": [
235
-
"cai"
236
-
],
237
-
"version": "0.2.1"
238
-
}
239
-
},
240
"chatgpt": {
241
"attrs": {
242
"meta": {
···
337
}
338
},
339
"github": {
340
-
"hash": "sha256-wO63G2mdpz2FWjatVY5R+L7Chki087Ev7oMfpgyOnxM=",
341
"owner": "williamkray",
342
"repo": "maubot-communitybot",
343
-
"rev": "v0.1.7"
344
},
345
"manifest": {
346
"database": true,
···
355
"modules": [
356
"community"
357
],
358
-
"version": "0.1.7"
359
}
360
},
361
"dice": {
···
542
}
543
},
544
"github": {
545
-
"hash": "sha256-VtZp4c3bbKCgbqQoJRnkle7Qn1zSGhgSPFAIlijQDOs=",
546
"owner": "williamkray",
547
"repo": "maubot-gifme",
548
-
"rev": "a896a07fba53c90455431e79904f79d949c91f92"
549
},
550
"manifest": {
551
"database": true,
···
560
"modules": [
561
"gifme"
562
],
563
-
"version": "0.1.0"
564
}
565
},
566
"giphy": {
···
603
}
604
},
605
"github": {
606
-
"hash": "sha256-Qc0KH8iGqMDa+1BXaB5fHtRIcsZRpTF2IufGMEXqV6Q=",
607
"owner": "maubot",
608
"repo": "github",
609
-
"rev": "v0.1.2"
610
},
611
"isOfficial": true,
612
"manifest": {
···
618
"id": "xyz.maubot.github",
619
"license": "AGPL-3.0-or-later",
620
"main_class": "GitHubBot",
621
-
"maubot": "0.3.0",
622
"modules": [
623
"github"
624
],
625
-
"version": "0.1.2",
626
"webapp": true
627
}
628
},
···
796
"webapp": false
797
}
798
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
799
"invite": {
800
"attrs": {
801
"meta": {
···
867
}
868
},
869
"github": {
870
-
"hash": "sha256-6bggnk3196M0eCkfYTJWLhiIwIVTtluffQzc58yIYzw=",
871
"owner": "williamkray",
872
"repo": "maubot-join",
873
-
"rev": "v0.3.1"
874
},
875
"manifest": {
876
"database": false,
···
884
"modules": [
885
"join"
886
],
887
-
"version": "0.3.1"
888
}
889
},
890
"karma": {
···
1126
"description": "A plugin create Discourse forum post from messages in Matrix or Bridged rooms and perform advanced forum searches directly from Matrix or Bridged rooms. Perfect for community building and engagement.",
1127
"downloadPage": "https://github.com/gitayam/matrix-to-discourse/releases",
1128
"homepage": "https://github.com/gitayam/matrix-to-discourse"
1129
-
}
0
1130
},
1131
"github": {
1132
-
"hash": "sha256-QIFgCQL9O/SVemXfxlXzPcPQ/qx68IU7ntArCk946iA=",
1133
"owner": "gitayam",
1134
"repo": "matrix-to-discourse",
1135
-
"rev": "v0.1.0.1"
1136
},
1137
"manifest": {
0
0
1138
"dependencies": [
1139
-
"aiohttp",
1140
-
"maubot",
1141
-
"mautrix",
1142
"openai",
1143
-
"pyyaml",
1144
-
"requests"
1145
],
1146
-
"id": "com.irregularchat.matrix_to_discourse",
0
0
0
1147
"license": "GPL-3.0",
1148
"main_class": "MatrixToDiscourseBot",
1149
"maubot": "0.1.0",
1150
"modules": [
1151
-
"bot"
1152
],
1153
-
"version": "0.1.0.0"
1154
}
1155
},
1156
"media": {
···
1214
}
1215
},
1216
"gitlab": {
1217
-
"hash": "sha256-6522dVqhGoPc/qjz65D3kXHks5LLb3yVe0K5abqdXrw=",
1218
"owner": "999eagle",
1219
"repo": "maubot-ntfy",
1220
-
"rev": "256aa8f315cbb184eba0256c2ec818abbdd2d408"
1221
},
1222
"manifest": {
1223
"config": true,
···
1249
}
1250
},
1251
"github": {
1252
-
"hash": "sha256-vw2MT4pwmUUWolgzkq0nZ/YaAlKUANrN0NPXXFf7B1k=",
1253
"owner": "tcpipuk",
1254
"repo": "maubot-openai-translate",
1255
-
"rev": "v0.3.1"
1256
},
1257
"manifest": {
1258
"config": true,
···
1266
"modules": [
1267
"openaitranslate"
1268
],
1269
-
"version": "0.3.1"
1270
}
1271
},
1272
"ovgumensabot": {
···
1279
}
1280
},
1281
"github": {
1282
-
"hash": "sha256-nuOLUPwE0F15FgOtbq3+qmNNd2eHRrRNJPMM+v1Ksy0=",
1283
"owner": "v411e",
1284
"repo": "ovgumensabot",
1285
-
"rev": "v0.0.8"
1286
},
1287
"manifest": {
1288
"database": true,
···
1300
"modules": [
1301
"ovgumensabot"
1302
],
1303
-
"version": "0.0.8"
1304
}
1305
},
1306
"pingcheck": {
···
1395
"pretix-inviter": {
1396
"attrs": {
1397
"meta": {
1398
-
"changelog": "https://github.com/fedora-infra/maubot-pretix-invite/blob/v0.3.2/CHANGELOG.md",
1399
"description": "A maubot plugin for inviting event participants from the pretix ticketing platform into a matrix room",
1400
"downloadPage": "https://github.com/fedora-infra/maubot-pretix-invite/releases",
1401
"homepage": "https://github.com/fedora-infra/maubot-pretix-invite"
1402
}
1403
},
1404
"github": {
1405
-
"hash": "sha256-KgWGvZ7QHcH0/u6+kodW8MAXtco4MM5MpbKscW903nQ=",
1406
"owner": "fedora-infra",
1407
"repo": "maubot-pretix-invite",
1408
-
"rev": "v0.3.2"
1409
},
1410
"manifest": {
1411
"config": true,
···
1418
"modules": [
1419
"event_helper"
1420
],
1421
-
"version": "0.3.2",
1422
"webapp": true
1423
}
1424
},
···
1654
}
1655
},
1656
"github": {
1657
-
"hash": "sha256-p/xJpJbzsOeQGcowvOhJSclPtmZyNyBaZBz+mexVqIY=",
1658
"owner": "maubot",
1659
"repo": "rss",
1660
-
"rev": "v0.3.2"
1661
},
1662
"isOfficial": true,
1663
"manifest": {
···
1676
"modules": [
1677
"rss"
1678
],
1679
-
"version": "0.3.2"
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1680
}
1681
},
1682
"satwcomic": {
···
1783
}
1784
},
1785
"github": {
1786
-
"hash": "sha256-naHY6f034uGnPIHidI7WXjcf2h/t0IYaPkO5QfKkXMs=",
1787
"owner": "ggogel",
1788
"repo": "SocialMediaDownloadMaubot",
1789
-
"rev": "1.4.2"
1790
},
1791
"manifest": {
1792
"config": true,
···
1802
"instaloader",
1803
"socialmediadownload"
1804
],
1805
-
"version": "1.4.2"
1806
}
1807
},
1808
"songwhip": {
···
66
}
67
},
68
"github": {
69
+
"hash": "sha256-RUwZ6SOsWiygyb10GnDmvskAurSiW9rFwDylYgr6wII=",
70
"owner": "rom4nik",
71
"repo": "maubot-alternatingcaps",
72
+
"rev": "v0.1.3"
73
},
74
"manifest": {
75
"id": "pl.rom4nik.maubot.alternatingcaps",
76
"license": "MIT",
77
"main_class": "AlternatingCaps",
78
+
"maubot": "0.4.0",
79
"modules": [
80
"alternatingcaps"
81
],
82
+
"version": "0.1.3"
83
}
84
},
85
"animemanga": {
···
203
"version": "1.0.0"
204
}
205
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
206
"chatgpt": {
207
"attrs": {
208
"meta": {
···
303
}
304
},
305
"github": {
306
+
"hash": "sha256-DNKdlbxeLdxb/OSujANzlZkgX1Bg6Q+4Ubxwq/0QV5M=",
307
"owner": "williamkray",
308
"repo": "maubot-communitybot",
309
+
"rev": "v0.1.17"
310
},
311
"manifest": {
312
"database": true,
···
321
"modules": [
322
"community"
323
],
324
+
"version": "0.1.17"
325
}
326
},
327
"dice": {
···
508
}
509
},
510
"github": {
511
+
"hash": "sha256-071iR5GlO+1WfMm6IK7by5nDfPhfOJCPr6WwB6qew/U=",
512
"owner": "williamkray",
513
"repo": "maubot-gifme",
514
+
"rev": "v0.1.1"
515
},
516
"manifest": {
517
"database": true,
···
526
"modules": [
527
"gifme"
528
],
529
+
"version": "0.1.1"
530
}
531
},
532
"giphy": {
···
569
}
570
},
571
"github": {
572
+
"hash": "sha256-XTX600ugWnaXyk1SFRwXWGCwRLcjXDBo1Vy0BG4kj5g=",
573
"owner": "maubot",
574
"repo": "github",
575
+
"rev": "v0.2.0"
576
},
577
"isOfficial": true,
578
"manifest": {
···
584
"id": "xyz.maubot.github",
585
"license": "AGPL-3.0-or-later",
586
"main_class": "GitHubBot",
587
+
"maubot": "0.4.1",
588
"modules": [
589
"github"
590
],
591
+
"version": "0.2.0",
592
"webapp": true
593
}
594
},
···
762
"webapp": false
763
}
764
},
765
+
"idonthavespotify": {
766
+
"attrs": {
767
+
"meta": {
768
+
"changelog": "https://github.com/HarHarLinks/maubot-idonthavespotify/releases",
769
+
"description": "Reply to Spotify links with alternative streaming services.",
770
+
"downloadPage": "https://github.com/HarHarLinks/maubot-idonthavespotify/releases",
771
+
"homepage": "https://github.com/HarHarLinks/maubot-idonthavespotify"
772
+
}
773
+
},
774
+
"github": {
775
+
"hash": "sha256-BFB/eyl1+I5P65RCSNYwEeitGCWBB8u7qpd70qLFJuY=",
776
+
"owner": "HarHarLinks",
777
+
"repo": "maubot-idonthavespotify",
778
+
"rev": "v1.1.0"
779
+
},
780
+
"manifest": {
781
+
"config": true,
782
+
"extra_files": [
783
+
"base-config.yaml"
784
+
],
785
+
"id": "de.sosnowkadub.idonthavespotify",
786
+
"license": "MIT",
787
+
"main_class": "idonthavespotify/IDontHaveSpotifyPlugin",
788
+
"maubot": "0.1.0",
789
+
"modules": [
790
+
"idonthavespotify"
791
+
],
792
+
"version": "1.1.0"
793
+
}
794
+
},
795
"invite": {
796
"attrs": {
797
"meta": {
···
863
}
864
},
865
"github": {
866
+
"hash": "sha256-ML4NEqn5fa/rBqzrocq0bUiktr81eyh4Uob5lJak+lk=",
867
"owner": "williamkray",
868
"repo": "maubot-join",
869
+
"rev": "v0.3.2"
870
},
871
"manifest": {
872
"database": false,
···
880
"modules": [
881
"join"
882
],
883
+
"version": "0.3.2"
884
}
885
},
886
"karma": {
···
1122
"description": "A plugin create Discourse forum post from messages in Matrix or Bridged rooms and perform advanced forum searches directly from Matrix or Bridged rooms. Perfect for community building and engagement.",
1123
"downloadPage": "https://github.com/gitayam/matrix-to-discourse/releases",
1124
"homepage": "https://github.com/gitayam/matrix-to-discourse"
1125
+
},
1126
+
"postPatch": "cd plugin"
1127
},
1128
"github": {
1129
+
"hash": "sha256-GMLpfpNsDKX/3PPeWrHwMVq8ppygJTPY/QhKe1JDphE=",
1130
"owner": "gitayam",
1131
"repo": "matrix-to-discourse",
1132
+
"rev": "v1.2.1"
1133
},
1134
"manifest": {
1135
+
"config": true,
1136
+
"database": false,
1137
"dependencies": [
0
0
0
1138
"openai",
1139
+
"pyyaml"
0
1140
],
1141
+
"extra_files": [
1142
+
"base-config.yaml"
1143
+
],
1144
+
"id": "url.irregularchat.matrix_to_discourse",
1145
"license": "GPL-3.0",
1146
"main_class": "MatrixToDiscourseBot",
1147
"maubot": "0.1.0",
1148
"modules": [
1149
+
"MatrixToDiscourseBot"
1150
],
1151
+
"version": "1.2.1"
1152
}
1153
},
1154
"media": {
···
1212
}
1213
},
1214
"gitlab": {
1215
+
"hash": "sha256-8Xsw/yO5Ma4weKAhk8DPQeCrn2ksk9c7J3oRzlAy2rw=",
1216
"owner": "999eagle",
1217
"repo": "maubot-ntfy",
1218
+
"rev": "4e930c0e7100e06570707564fc471fc3c931708e"
1219
},
1220
"manifest": {
1221
"config": true,
···
1247
}
1248
},
1249
"github": {
1250
+
"hash": "sha256-PoHZhMy5sCgl1pf6xfbFpF0J9cSNk/NaVm6XeIgeAzU=",
1251
"owner": "tcpipuk",
1252
"repo": "maubot-openai-translate",
1253
+
"rev": "v0.4.0"
1254
},
1255
"manifest": {
1256
"config": true,
···
1264
"modules": [
1265
"openaitranslate"
1266
],
1267
+
"version": "0.4.0"
1268
}
1269
},
1270
"ovgumensabot": {
···
1277
}
1278
},
1279
"github": {
1280
+
"hash": "sha256-Gzw6YWvku0PbN/sNKABGjPPOpskubOHUVuiwMjD3m+c=",
1281
"owner": "v411e",
1282
"repo": "ovgumensabot",
1283
+
"rev": "v0.0.9"
1284
},
1285
"manifest": {
1286
"database": true,
···
1298
"modules": [
1299
"ovgumensabot"
1300
],
1301
+
"version": "0.0.9"
1302
}
1303
},
1304
"pingcheck": {
···
1393
"pretix-inviter": {
1394
"attrs": {
1395
"meta": {
1396
+
"changelog": "https://github.com/fedora-infra/maubot-pretix-invite/blob/v0.4.1.1/CHANGELOG.md",
1397
"description": "A maubot plugin for inviting event participants from the pretix ticketing platform into a matrix room",
1398
"downloadPage": "https://github.com/fedora-infra/maubot-pretix-invite/releases",
1399
"homepage": "https://github.com/fedora-infra/maubot-pretix-invite"
1400
}
1401
},
1402
"github": {
1403
+
"hash": "sha256-3LfIh4THe9lGl2RJHuXA1SKJ9pvi8851F8n+HPSID+o=",
1404
"owner": "fedora-infra",
1405
"repo": "maubot-pretix-invite",
1406
+
"rev": "v0.4.1.1"
1407
},
1408
"manifest": {
1409
"config": true,
···
1416
"modules": [
1417
"event_helper"
1418
],
1419
+
"version": "0.4.1",
1420
"webapp": true
1421
}
1422
},
···
1652
}
1653
},
1654
"github": {
1655
+
"hash": "sha256-1Wac/j8qOTA31BCI4emOSYAEYEbtOjdB5ACz1qnY6h8=",
1656
"owner": "maubot",
1657
"repo": "rss",
1658
+
"rev": "v0.4.1"
1659
},
1660
"isOfficial": true,
1661
"manifest": {
···
1674
"modules": [
1675
"rss"
1676
],
1677
+
"version": "0.4.1"
1678
+
}
1679
+
},
1680
+
"rsvc": {
1681
+
"attrs": {
1682
+
"meta": {
1683
+
"changelog": "https://github.com/maubot/rsvc/releases",
1684
+
"description": "A bot to check the version of servers in room.",
1685
+
"downloadPage": "https://github.com/maubot/rsvc/releases",
1686
+
"homepage": "https://github.com/maubot/rsvc"
1687
+
}
1688
+
},
1689
+
"github": {
1690
+
"hash": "sha256-4VvC2a0WZ9mlwV4l1Nz9eWatCy0nbhEXFhoAhUhrT1A=",
1691
+
"owner": "maubot",
1692
+
"repo": "rsvc",
1693
+
"rev": "d67750085437fd50a6054bc1b6623b1a1341c0b8"
1694
+
},
1695
+
"isOfficial": true,
1696
+
"manifest": {
1697
+
"extra_files": [
1698
+
"base-config.yaml"
1699
+
],
1700
+
"id": "xyz.maubot.rsvc",
1701
+
"license": "AGPL-3.0-or-later",
1702
+
"main_class": "ServerCheckerBot",
1703
+
"maubot": "0.1.0",
1704
+
"modules": [
1705
+
"rsvc"
1706
+
],
1707
+
"version": "1.0.0"
1708
}
1709
},
1710
"satwcomic": {
···
1811
}
1812
},
1813
"github": {
1814
+
"hash": "sha256-pea3NlDExMkgfWfP003xO5Nt+RnidpVq9PzDOxzz7Ow=",
1815
"owner": "ggogel",
1816
"repo": "SocialMediaDownloadMaubot",
1817
+
"rev": "1.4.4"
1818
},
1819
"manifest": {
1820
"config": true,
···
1830
"instaloader",
1831
"socialmediadownload"
1832
],
1833
+
"version": "1.4.4"
1834
}
1835
},
1836
"songwhip": {
+142
-114
pkgs/tools/networking/maubot/plugins/update.py
···
10
import toml
11
import zipfile
12
13
-
from typing import Dict, List
14
-
15
HOSTNAMES = {
16
-
'git.skeg1.se': 'gitlab',
17
-
'edugit.org': 'gitlab',
18
-
'codeberg.org': 'gitea',
19
}
20
-
PLUGINS: Dict[str, dict] = {}
0
0
0
21
22
-
yaml = ruamel.yaml.YAML(typ='safe')
23
24
-
TMP = os.environ.get('TEMPDIR', '/tmp')
0
25
26
def process_repo(path: str, official: bool):
27
global PLUGINS
28
-
with open(path, 'rt') as f:
29
data = yaml.load(f)
30
-
name, repourl, license, desc = data['name'], data['repo'], data['license'], data['description']
0
0
0
0
0
0
0
31
origurl = repourl
32
-
if '/' in name or ' ' in name:
33
-
name = os.path.split(path)[-1].removesuffix('.yaml')
34
-
name = name.replace('_', '-').lower()
35
if name in PLUGINS.keys():
36
-
raise ValueError(f'Duplicate plugin {name}, refusing to continue')
37
-
repodir = os.path.join(TMP, 'maubot-plugins', name)
38
plugindir = repodir
39
-
if '/tree/' in repourl:
40
-
repourl, rev_path = repourl.split('/tree/')
41
-
rev, subdir = rev_path.strip('/').split('/')
0
0
0
42
plugindir = os.path.join(plugindir, subdir)
43
else:
44
rev = None
45
subdir = None
46
47
-
if repourl.startswith('http:'):
48
-
repourl = 'https' + repourl[4:]
49
-
repourl = repourl.rstrip('/')
50
if not os.path.exists(repodir):
51
-
print('Fetching', name)
52
-
repo = git.Repo.clone_from(repourl + '.git', repodir)
53
else:
54
repo = git.Repo(repodir)
55
tags = sorted(repo.tags, key=lambda t: t.commit.committed_datetime)
56
-
tags = list(filter(lambda x: 'rc' not in str(x), tags))
57
if tags:
58
repo.git.checkout(tags[-1])
59
rev = str(tags[-1])
60
else:
61
-
rev = str(repo.commit('HEAD'))
62
-
ret: dict = {'attrs':{}}
63
if subdir:
64
-
ret['attrs']['postPatch'] = f'cd {subdir}'
65
-
domain, query = repourl.removeprefix('https://').split('/', 1)
66
-
hash = subprocess.run([
67
-
'nurl',
68
-
'--hash',
69
-
f'file://{repodir}',
70
-
rev
71
-
], capture_output=True, check=True).stdout.decode('utf-8')
72
-
ret['attrs']['meta'] = {
73
-
'description': desc,
74
-
'homepage': origurl,
75
}
76
-
if domain == 'github.com':
77
-
owner, repo = query.split('/')
78
-
ret['github'] = {
79
-
'owner': owner,
80
-
'repo': repo,
81
-
'rev': rev,
82
-
'hash': hash,
83
}
84
-
ret['attrs']['meta']['downloadPage'] = f'{repourl}/releases'
85
-
ret['attrs']['meta']['changelog'] = f'{repourl}/releases'
86
-
repobase = f'{repourl}/blob/{rev}'
87
-
elif HOSTNAMES.get(domain, 'gitea' if 'gitea.' in domain or 'forgejo.' in domain else None) == 'gitea':
88
-
owner, repo = query.split('/')
89
-
ret['gitea'] = {
90
-
'domain': domain,
91
-
'owner': owner,
92
-
'repo': repo,
93
-
'rev': rev,
94
-
'hash': hash,
0
0
0
0
0
95
}
96
-
repobase = f'{repourl}/src/commit/{rev}'
97
-
ret['attrs']['meta']['downloadPage'] = f'{repourl}/releases'
98
-
ret['attrs']['meta']['changelog'] = f'{repourl}/releases'
99
-
elif HOSTNAMES.get(domain, 'gitlab' if 'gitlab.' in domain else None) == 'gitlab':
100
-
owner, repo = query.split('/')
101
-
ret['gitlab'] = {
102
-
'owner': owner,
103
-
'repo': repo,
104
-
'rev': rev,
105
-
'hash': hash,
106
}
107
-
if domain != 'gitlab.com':
108
-
ret['gitlab']['domain'] = domain
109
-
repobase = f'{repourl}/-/blob/{rev}'
110
else:
111
-
raise ValueError(f'Is {domain} Gitea or Gitlab, or something else? Please specify in the Python script!')
112
-
if os.path.exists(os.path.join(plugindir, 'CHANGELOG.md')):
113
-
ret['attrs']['meta']['changelog'] = f'{repobase}/CHANGELOG.md'
114
-
if os.path.exists(os.path.join(plugindir, 'maubot.yaml')):
115
-
with open(os.path.join(plugindir, 'maubot.yaml'), 'rt') as f:
116
-
ret['manifest'] = yaml.load(f)
117
-
elif os.path.exists(os.path.join(plugindir, 'pyproject.toml')):
118
-
ret['isPoetry'] = True
119
-
with open(os.path.join(plugindir, 'pyproject.toml'), 'rt') as f:
0
0
120
data = toml.load(f)
121
deps = []
122
-
for key, val in data['tool']['poetry'].get('dependencies', {}).items():
123
-
if key in ['maubot', 'mautrix', 'python']:
124
continue
125
reqs = []
126
-
for req in val.split(','):
127
reqs.extend(poetry_to_pep(req))
128
-
deps.append(key + ', '.join(reqs))
129
-
ret['manifest'] = data['tool']['maubot']
130
-
ret['manifest']['id'] = data['tool']['poetry']['name']
131
-
ret['manifest']['version'] = data['tool']['poetry']['version']
132
-
ret['manifest']['license'] = data['tool']['poetry']['license']
133
if deps:
134
-
ret['manifest']['dependencies'] = deps
135
else:
136
-
raise ValueError(f'No maubot.yaml or pyproject.toml found in {repodir}')
137
# normalize non-spdx-conformant licenses this way
138
# (and fill out missing license info)
139
-
if 'license' not in ret['manifest'] or ret['manifest']['license'] in ['GPLv3', 'AGPL 3.0']:
140
-
ret['attrs']['meta']['license'] = license
141
-
elif ret['manifest']['license'] != license:
142
-
print(f"Warning: licenses for {repourl} don't match! {ret['manifest']['license']} != {license}")
0
0
0
0
0
143
if official:
144
-
ret['isOfficial'] = official
145
PLUGINS[name] = ret
0
146
147
def next_incomp(ver_s: str) -> str:
148
-
ver = ver_s.split('.')
149
zero = False
150
for i in range(len(ver)):
151
try:
···
156
break
157
continue
158
if zero:
159
-
ver[i] = '0'
160
elif seg:
161
ver[i] = str(seg + 1)
162
zero = True
163
-
return '.'.join(ver)
164
165
-
def poetry_to_pep(ver_req: str) -> List[str]:
166
-
if '*' in ver_req:
167
-
raise NotImplementedError('Wildcard poetry versions not implemented!')
168
-
if ver_req.startswith('^'):
169
-
return ['>=' + ver_req[1:], '<' + next_incomp(ver_req[1:])]
170
-
if ver_req.startswith('~'):
171
-
return ['~=' + ver_req[1:]]
0
172
return [ver_req]
0
173
174
def main():
175
-
cache_path = os.path.join(TMP, 'maubot-plugins')
176
if not os.path.exists(cache_path):
177
os.makedirs(cache_path)
178
-
git.Repo.clone_from('https://github.com/maubot/plugins.maubot.xyz', os.path.join(cache_path, '_repo'))
0
0
0
179
else:
180
pass
181
182
-
repodir = os.path.join(cache_path, '_repo')
183
184
-
for suffix, official in (('official', True), ('thirdparty', False)):
185
-
directory = os.path.join(repodir, 'data', 'plugins', suffix)
186
for plugin_name in os.listdir(directory):
187
process_repo(os.path.join(directory, plugin_name), official)
188
189
-
if os.path.isdir('pkgs/tools/networking/maubot/plugins'):
190
-
generated = 'pkgs/tools/networking/maubot/plugins/generated.json'
191
else:
192
script_dir = os.path.dirname(os.path.realpath(__file__))
193
-
generated = os.path.join(script_dir, 'generated.json')
194
195
-
with open(generated, 'wt') as file:
196
-
json.dump(PLUGINS, file, indent=' ', separators=(',', ': '), sort_keys=True)
197
-
file.write('\n')
198
199
-
if __name__ == '__main__':
0
200
main()
···
10
import toml
11
import zipfile
12
0
0
13
HOSTNAMES = {
14
+
"git.skeg1.se": "gitlab",
15
+
"edugit.org": "gitlab",
16
+
"codeberg.org": "gitea",
17
}
18
+
PLUGINS: dict[str, dict] = {}
19
+
# https://github.com/maubot/plugins.maubot.xyz/pull/45
20
+
SKIP = {"characterai"}
21
+
DIRS = {"matrix-to-discourse": "plugin"}
22
23
+
yaml = ruamel.yaml.YAML(typ="safe")
24
25
+
TMP = os.environ.get("TEMPDIR", "/tmp")
26
+
27
28
def process_repo(path: str, official: bool):
29
global PLUGINS
30
+
with open(path, "rt") as f:
31
data = yaml.load(f)
32
+
name, repourl, license, desc = (
33
+
data["name"],
34
+
data["repo"],
35
+
data["license"],
36
+
data["description"],
37
+
)
38
+
if name in SKIP:
39
+
return
40
origurl = repourl
41
+
if "/" in name or " " in name:
42
+
name = os.path.split(path)[-1].removesuffix(".yaml")
43
+
name = name.replace("_", "-").lower()
44
if name in PLUGINS.keys():
45
+
raise ValueError(f"Duplicate plugin {name}, refusing to continue")
46
+
repodir = os.path.join(TMP, "maubot-plugins", name)
47
plugindir = repodir
48
+
if "/tree/" in repourl:
49
+
repourl, rev_path = repourl.split("/tree/")
50
+
rev, subdir = rev_path.strip("/").split("/")
51
+
plugindir = os.path.join(plugindir, subdir)
52
+
elif name in DIRS.keys():
53
+
subdir = DIRS[name]
54
plugindir = os.path.join(plugindir, subdir)
55
else:
56
rev = None
57
subdir = None
58
59
+
if repourl.startswith("http:"):
60
+
repourl = "https" + repourl[4:]
61
+
repourl = repourl.rstrip("/")
62
if not os.path.exists(repodir):
63
+
print("Fetching", name)
64
+
repo = git.Repo.clone_from(repourl + ".git", repodir)
65
else:
66
repo = git.Repo(repodir)
67
tags = sorted(repo.tags, key=lambda t: t.commit.committed_datetime)
68
+
tags = list(filter(lambda x: "rc" not in str(x), tags))
69
if tags:
70
repo.git.checkout(tags[-1])
71
rev = str(tags[-1])
72
else:
73
+
rev = str(repo.commit("HEAD"))
74
+
ret: dict = {"attrs": {}}
75
if subdir:
76
+
ret["attrs"]["postPatch"] = f"cd {subdir}"
77
+
domain, query = repourl.removeprefix("https://").split("/", 1)
78
+
hash = subprocess.run(
79
+
["nurl", "--hash", f"file://{repodir}", rev], capture_output=True, check=True
80
+
).stdout.decode("utf-8")
81
+
ret["attrs"]["meta"] = {
82
+
"description": desc,
83
+
"homepage": origurl,
0
0
0
84
}
85
+
if domain == "github.com":
86
+
owner, repo = query.split("/")
87
+
ret["github"] = {
88
+
"owner": owner,
89
+
"repo": repo,
90
+
"rev": rev,
91
+
"hash": hash,
92
}
93
+
ret["attrs"]["meta"]["downloadPage"] = f"{repourl}/releases"
94
+
ret["attrs"]["meta"]["changelog"] = f"{repourl}/releases"
95
+
repobase = f"{repourl}/blob/{rev}"
96
+
elif (
97
+
HOSTNAMES.get(
98
+
domain, "gitea" if "gitea." in domain or "forgejo." in domain else None
99
+
)
100
+
== "gitea"
101
+
):
102
+
owner, repo = query.split("/")
103
+
ret["gitea"] = {
104
+
"domain": domain,
105
+
"owner": owner,
106
+
"repo": repo,
107
+
"rev": rev,
108
+
"hash": hash,
109
}
110
+
repobase = f"{repourl}/src/commit/{rev}"
111
+
ret["attrs"]["meta"]["downloadPage"] = f"{repourl}/releases"
112
+
ret["attrs"]["meta"]["changelog"] = f"{repourl}/releases"
113
+
elif HOSTNAMES.get(domain, "gitlab" if "gitlab." in domain else None) == "gitlab":
114
+
owner, repo = query.split("/")
115
+
ret["gitlab"] = {
116
+
"owner": owner,
117
+
"repo": repo,
118
+
"rev": rev,
119
+
"hash": hash,
120
}
121
+
if domain != "gitlab.com":
122
+
ret["gitlab"]["domain"] = domain
123
+
repobase = f"{repourl}/-/blob/{rev}"
124
else:
125
+
raise ValueError(
126
+
f"Is {domain} Gitea or Gitlab, or something else? Please specify in the Python script!"
127
+
)
128
+
if os.path.exists(os.path.join(plugindir, "CHANGELOG.md")):
129
+
ret["attrs"]["meta"]["changelog"] = f"{repobase}/CHANGELOG.md"
130
+
if os.path.exists(os.path.join(plugindir, "maubot.yaml")):
131
+
with open(os.path.join(plugindir, "maubot.yaml"), "rt") as f:
132
+
ret["manifest"] = yaml.load(f)
133
+
elif os.path.exists(os.path.join(plugindir, "pyproject.toml")):
134
+
ret["isPoetry"] = True
135
+
with open(os.path.join(plugindir, "pyproject.toml"), "rt") as f:
136
data = toml.load(f)
137
deps = []
138
+
for key, val in data["tool"]["poetry"].get("dependencies", {}).items():
139
+
if key in ["maubot", "mautrix", "python"]:
140
continue
141
reqs = []
142
+
for req in val.split(","):
143
reqs.extend(poetry_to_pep(req))
144
+
deps.append(key + ", ".join(reqs))
145
+
ret["manifest"] = data["tool"]["maubot"]
146
+
ret["manifest"]["id"] = data["tool"]["poetry"]["name"]
147
+
ret["manifest"]["version"] = data["tool"]["poetry"]["version"]
148
+
ret["manifest"]["license"] = data["tool"]["poetry"]["license"]
149
if deps:
150
+
ret["manifest"]["dependencies"] = deps
151
else:
152
+
raise ValueError(f"No maubot.yaml or pyproject.toml found in {repodir}")
153
# normalize non-spdx-conformant licenses this way
154
# (and fill out missing license info)
155
+
if "license" not in ret["manifest"] or ret["manifest"]["license"] in [
156
+
"GPLv3",
157
+
"AGPL 3.0",
158
+
]:
159
+
ret["attrs"]["meta"]["license"] = license
160
+
elif ret["manifest"]["license"] != license:
161
+
print(
162
+
f"Warning: licenses for {repourl} don't match! {ret['manifest']['license']} != {license}"
163
+
)
164
if official:
165
+
ret["isOfficial"] = official
166
PLUGINS[name] = ret
167
+
168
169
def next_incomp(ver_s: str) -> str:
170
+
ver = ver_s.split(".")
171
zero = False
172
for i in range(len(ver)):
173
try:
···
178
break
179
continue
180
if zero:
181
+
ver[i] = "0"
182
elif seg:
183
ver[i] = str(seg + 1)
184
zero = True
185
+
return ".".join(ver)
186
187
+
188
+
def poetry_to_pep(ver_req: str) -> list[str]:
189
+
if "*" in ver_req:
190
+
raise NotImplementedError("Wildcard poetry versions not implemented!")
191
+
if ver_req.startswith("^"):
192
+
return [">=" + ver_req[1:], "<" + next_incomp(ver_req[1:])]
193
+
if ver_req.startswith("~"):
194
+
return ["~=" + ver_req[1:]]
195
return [ver_req]
196
+
197
198
def main():
199
+
cache_path = os.path.join(TMP, "maubot-plugins")
200
if not os.path.exists(cache_path):
201
os.makedirs(cache_path)
202
+
git.Repo.clone_from(
203
+
"https://github.com/maubot/plugins.maubot.xyz",
204
+
os.path.join(cache_path, "_repo"),
205
+
)
206
else:
207
pass
208
209
+
repodir = os.path.join(cache_path, "_repo")
210
211
+
for suffix, official in (("official", True), ("thirdparty", False)):
212
+
directory = os.path.join(repodir, "data", "plugins", suffix)
213
for plugin_name in os.listdir(directory):
214
process_repo(os.path.join(directory, plugin_name), official)
215
216
+
if os.path.isdir("pkgs/tools/networking/maubot/plugins"):
217
+
generated = "pkgs/tools/networking/maubot/plugins/generated.json"
218
else:
219
script_dir = os.path.dirname(os.path.realpath(__file__))
220
+
generated = os.path.join(script_dir, "generated.json")
221
222
+
with open(generated, "wt") as file:
223
+
json.dump(PLUGINS, file, indent=" ", separators=(",", ": "), sort_keys=True)
224
+
file.write("\n")
225
226
+
227
+
if __name__ == "__main__":
228
main()