Compare commits

...

27 Commits

Author SHA1 Message Date
e067993a14 packages.missgram: 转发回复,并修改文案 2025-12-29 17:06:58 +08:00
ffd01db99b packages.missgram: 修改文案 2025-12-29 16:52:47 +08:00
e1879c6625 packages/missgram: fix 2025-12-29 14:06:23 +08:00
8587524732 flake.lib: allow generic module styles 2025-12-28 18:00:25 +08:00
8fba11e9a8 modules.packages.vscode: swith to nixd 2025-12-28 17:40:51 +08:00
1de9f717ab modules.services.missgram: fix 2025-12-28 17:16:00 +08:00
3a34d1e962 packages.missgram: fix 2025-12-28 15:40:25 +08:00
f7deb945ae packages/missgram: save info to db 2025-12-28 10:46:52 +08:00
c3e1d2bfb7 devices.pc: enable postgresql 2025-12-27 16:23:42 +08:00
8166c7ecee packages/missgram: init sql depencency 2025-12-27 16:02:40 +08:00
157dd0e844 packages/reflectcpp,sqlgen: init 2025-12-27 15:46:15 +08:00
0c80dde1d1 packages/missgram: rename 2025-12-27 11:40:10 +08:00
4d1f6eb6b5 packages.misskey-forwarder: fix 2025-12-26 13:35:01 +08:00
bf922747d5 packages/misskey-forwarder: fix renote link 2025-12-26 12:38:29 +08:00
a1b4aa7803 flake.dns: fix 2025-12-26 07:01:12 +08:00
3eb2495ebb flake.lib.buildNixpkgsConfig: remove valkey workaround 2025-12-25 23:12:53 +08:00
c36e0c52d6 packages/misskey-forwarder: init 2025-12-25 23:12:48 +08:00
222b0829c8 modules.packages.vscode: remove tab default keybinding 2025-12-25 17:53:45 +08:00
3b7e22fc52 Merge branch 'next' into production 2025-12-25 09:13:40 +08:00
5aebb72185 packages.ghostty/zellij: increase scrollback buffer size 2025-12-24 21:06:20 +08:00
08023306d6 modules.services.sshd: enable GatewayPorts 2025-12-24 14:28:28 +08:00
ea91a75380 Revert "modules.services.huggin: drop"
This reverts commit 7a7b645e9e.
2025-12-24 14:01:49 +08:00
94a0b81122 modules.user: add stq 2025-12-22 18:05:20 +08:00
4d10cb5301 modules.system.gui: add more startup apps 2025-12-22 12:58:10 +08:00
1d6a352978 modules.packages.zsh: enable fzf 2025-12-21 09:29:11 +08:00
58ea730d48 Revert "devices.pc: adjust cpu voltage and power settings"
This reverts commit 298b0e05f5.
2025-12-21 08:58:00 +08:00
298b0e05f5 devices.pc: adjust cpu voltage and power settings 2025-12-20 22:00:12 +08:00
38 changed files with 551 additions and 48 deletions

View File

@@ -12,6 +12,7 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBoDGk9HYphkngx2Ix/vef2ZntdVNK1kbS9pY8+TzI41
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJi6O1Sf1BBV1dYyH1jcHiws+ntwVfV29+6Paq1CQaET hss ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJi6O1Sf1BBV1dYyH1jcHiws+ntwVfV29+6Paq1CQaET hss
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFlBxisj3sU9QC8UC5gX6sakf7G03ybbkmHtD2cybuZA qmx ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFlBxisj3sU9QC8UC5gX6sakf7G03ybbkmHtD2cybuZA qmx
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAWU/OlrP8bJ5k7IqpIwUC1COuVsmrYVreW/ieEdPYdj ccy ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAWU/OlrP8bJ5k7IqpIwUC1COuVsmrYVreW/ieEdPYdj ccy
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILvXkM8TS8fDot22LTfU2jDVOqK20LmK8Rd7xO05vYns stq
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCmJoiGO5YD3lbbIOJ99Al2xxm6QS9q+dTCTtlALjYI5f9ICGZJT8PEGlV9BBNCRQdgb3i2LBzQi90Tq1oG6/PcTV3Mto2TawLz5+2+ym29eIq1QIhVTLmZskK815FpawWqxY6+xpGU3vP1WjrFBbhGtl+CCaN+P2TWNkrR8FjG2144hdAlFfEEqfQC+TXbsyJCYoExuxGDJo8ae0JGbz9w1A1UbjnHwKnoxvirTFEbw9IHJIcTdUwuQKOrwydboCOqeaHt74+BnnCOZhpYqMDacrknHITN4GfFFzbs6FsE8NAwFk6yvkNXXzoe60iveNXtCIYuWjG517LQgHAC5BdaPgqzYNg+eqSul72e+jjRs+KDioNqvprw+TcBBO1lXZ2VQFyWyAdV2Foyaz3Wk5qYlOpX/9JLEp6H3cU0XCFR25FdXmjQ4oXN1QEe+2akV8MQ9cWhFhDcbY8Q1EiMWpBVC1xbt4FwE8VCTByZOZsQ0wPVe/vkjANOo+brS3tsR18= 00@xmuhpc ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCmJoiGO5YD3lbbIOJ99Al2xxm6QS9q+dTCTtlALjYI5f9ICGZJT8PEGlV9BBNCRQdgb3i2LBzQi90Tq1oG6/PcTV3Mto2TawLz5+2+ym29eIq1QIhVTLmZskK815FpawWqxY6+xpGU3vP1WjrFBbhGtl+CCaN+P2TWNkrR8FjG2144hdAlFfEEqfQC+TXbsyJCYoExuxGDJo8ae0JGbz9w1A1UbjnHwKnoxvirTFEbw9IHJIcTdUwuQKOrwydboCOqeaHt74+BnnCOZhpYqMDacrknHITN4GfFFzbs6FsE8NAwFk6yvkNXXzoe60iveNXtCIYuWjG517LQgHAC5BdaPgqzYNg+eqSul72e+jjRs+KDioNqvprw+TcBBO1lXZ2VQFyWyAdV2Foyaz3Wk5qYlOpX/9JLEp6H3cU0XCFR25FdXmjQ4oXN1QEe+2akV8MQ9cWhFhDcbY8Q1EiMWpBVC1xbt4FwE8VCTByZOZsQ0wPVe/vkjANOo+brS3tsR18= 00@xmuhpc
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxcIWDQxVyIRqCGR4uWtrh4tLc025+q6du2GVsox8IzmBFkjNY8Au5GIMP5BKRstxFdg3f/wam8krckUN9rv5+OHB9U8HGz77Xs0FktqRVNMaDPdptePZQJ9A9eW3kkFDfQnORJtiVcEWfUBS3pi0QFOHylnG27YyC/Vjx9tjvtJWKsQEVTFJbFHPdi+G7lHTpqIGx+/a2JN9O6uVujXXYvjSVXsd+CWB9VMZMvYCIz2Ecb6RqR3brj4FhRRl8zyCj+J4ACYFdGWL98fTab2uPHbpVeKrefFFA43JOD/4zwBx/uw7MAQAq0GunTV3FpBfIAQHWgftf2fSlbz20oPjCwdYn9ZuGJOBUroryex7AKZmnSYM3biLHcctQfZtxqVPEU3W/62MUsI/kZb9RcF24JRksMoS2XWTiv2HFf5ijQGLXXOjqiTlGncwiKf65DwkDBsSxzgbXk5Uo86viq6UITFXPx/RytU+SUiN4Wb7wcBTjt/+tyQd1uqc7+3DCDXk= 01@xmuhpc ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxcIWDQxVyIRqCGR4uWtrh4tLc025+q6du2GVsox8IzmBFkjNY8Au5GIMP5BKRstxFdg3f/wam8krckUN9rv5+OHB9U8HGz77Xs0FktqRVNMaDPdptePZQJ9A9eW3kkFDfQnORJtiVcEWfUBS3pi0QFOHylnG27YyC/Vjx9tjvtJWKsQEVTFJbFHPdi+G7lHTpqIGx+/a2JN9O6uVujXXYvjSVXsd+CWB9VMZMvYCIz2Ecb6RqR3brj4FhRRl8zyCj+J4ACYFdGWL98fTab2uPHbpVeKrefFFA43JOD/4zwBx/uw7MAQAq0GunTV3FpBfIAQHWgftf2fSlbz20oPjCwdYn9ZuGJOBUroryex7AKZmnSYM3biLHcctQfZtxqVPEU3W/62MUsI/kZb9RcF24JRksMoS2XWTiv2HFf5ijQGLXXOjqiTlGncwiKf65DwkDBsSxzgbXk5Uo86viq6UITFXPx/RytU+SUiN4Wb7wcBTjt/+tyQd1uqc7+3DCDXk= 01@xmuhpc

View File

@@ -55,6 +55,7 @@ inputs:
nextcloud = {}; nextcloud = {};
freshrss = {}; freshrss = {};
send = {}; send = {};
huginn = {};
httpapi = {}; httpapi = {};
gitea = {}; gitea = {};
grafana = {}; grafana = {};

View File

@@ -54,10 +54,13 @@ vaultwarden:
admin_token: ENC[AES256_GCM,data:TrgqQwXBoCdsLeWQYkur4zS+Z4nCoDDoePnN5vm+AIcgYXVwjxcf/0AwXQIxVNEypYysPpoHKOigwhkf5kLazAMiBZ0goAflJT/S4nOLo90s+9kDCADXWnCeHNhBUg8fUulNPBbpqdfFKCJgJCD2WTI+V5yFLQ==,iv:maKU6pcxis7Cyrx9x26cUTBzA6ZKcKJWSP23w+MDehw=,tag:GYpPHp2slC6V8aKA1FHFAg==,type:str] admin_token: ENC[AES256_GCM,data:TrgqQwXBoCdsLeWQYkur4zS+Z4nCoDDoePnN5vm+AIcgYXVwjxcf/0AwXQIxVNEypYysPpoHKOigwhkf5kLazAMiBZ0goAflJT/S4nOLo90s+9kDCADXWnCeHNhBUg8fUulNPBbpqdfFKCJgJCD2WTI+V5yFLQ==,iv:maKU6pcxis7Cyrx9x26cUTBzA6ZKcKJWSP23w+MDehw=,tag:GYpPHp2slC6V8aKA1FHFAg==,type:str]
mariadb: mariadb:
freshrss: ENC[AES256_GCM,data:Qjg5GIX13ccZi/DuqtWK0qzr2GK0GzzUdEZWXDhUhGxFWzgosADxDCc8wfOchItaJFefnVrpPxdAPvT+4TEH0g==,iv:oGii3o6sJYVc11kdQMh0Pa3GUbWqttFgjvSVEbTycZc=,tag:8GWWwuJjQBwDFl9pJvg90g==,type:str] freshrss: ENC[AES256_GCM,data:Qjg5GIX13ccZi/DuqtWK0qzr2GK0GzzUdEZWXDhUhGxFWzgosADxDCc8wfOchItaJFefnVrpPxdAPvT+4TEH0g==,iv:oGii3o6sJYVc11kdQMh0Pa3GUbWqttFgjvSVEbTycZc=,tag:8GWWwuJjQBwDFl9pJvg90g==,type:str]
huginn: ENC[AES256_GCM,data:/hFQdG/RGrX75qd0+WgwhnwR7p/CEVx1vPksRSudxmc1m4VO/AVzgMCWAz4310ctTEnn4GZinvD6QGFta5IOSA==,iv:mrPDZA6Bnw+SPVDDe64tivvvQtHWvCsPJbEnPqm12g4=,tag:ihXbIJwwtQ0RfaNfcaop4Q==,type:str]
nextcloud: nextcloud:
admin: ENC[AES256_GCM,data:DJK+u19VP9cFvq4/P0+f7erXxZkRWI4NRrX9HdHO96xy9wZMtB+hEDN3zLQnkTTtmd2ZLs9+c9BsUNXZperGDQ==,iv:zX8Nxt5+O/mGVt5l1j8IojBkgxg5oDae6KWTXYz0hRE=,tag:MRyMx0OXYTCmtaySP/umNw==,type:str] admin: ENC[AES256_GCM,data:DJK+u19VP9cFvq4/P0+f7erXxZkRWI4NRrX9HdHO96xy9wZMtB+hEDN3zLQnkTTtmd2ZLs9+c9BsUNXZperGDQ==,iv:zX8Nxt5+O/mGVt5l1j8IojBkgxg5oDae6KWTXYz0hRE=,tag:MRyMx0OXYTCmtaySP/umNw==,type:str]
freshrss: freshrss:
chn: ENC[AES256_GCM,data:wwHntnMeiGZ5v8CE7CGV,iv:snIdYdFpvv5HvcR5qucD2pZXXef3dhSU+2wK5SPrDjw=,tag:2RnujKKkQSoxvSNZPLS9Pg==,type:str] chn: ENC[AES256_GCM,data:wwHntnMeiGZ5v8CE7CGV,iv:snIdYdFpvv5HvcR5qucD2pZXXef3dhSU+2wK5SPrDjw=,tag:2RnujKKkQSoxvSNZPLS9Pg==,type:str]
huginn:
invitationCode: ENC[AES256_GCM,data:E8rEdAfUQX9oJEnvxVF5PmYFMd9PN8+K,iv:gZtUf+AkICLHD4h2beHbEfyoL4bcoOv0sivDFDB3vVY=,tag:4tlsPuED6jCXNE0iOayXsg==,type:str]
grafana: grafana:
secret: ENC[AES256_GCM,data:O2L0+R9QvOMJLKa941nxn+FeuZ5nOAm1iDlKW2vvk5Dyod0XLdGL1seWuYzpx+NL16qmC1u8jydDcBfUT+PAeA==,iv:Pqsr+POPAr8djdVMK5U4PiS1zUnZXLH3q588D/jOMys=,tag:QziP0kKT5oyI/RHaYHr2mw==,type:str] secret: ENC[AES256_GCM,data:O2L0+R9QvOMJLKa941nxn+FeuZ5nOAm1iDlKW2vvk5Dyod0XLdGL1seWuYzpx+NL16qmC1u8jydDcBfUT+PAeA==,iv:Pqsr+POPAr8djdVMK5U4PiS1zUnZXLH3q588D/jOMys=,tag:QziP0kKT5oyI/RHaYHr2mw==,type:str]
chn: ENC[AES256_GCM,data:xMwWBYChRIxw5KDjgCYBJWkbRRo5FUtyhZ0+SVRIgjQ=,iv:EIjECQHx3/2t+oMC16B1Xfwa8guiST2pdIKM1hNcuFA=,tag:BP8ElnMevqF6urDgBP/UAg==,type:str] chn: ENC[AES256_GCM,data:xMwWBYChRIxw5KDjgCYBJWkbRRo5FUtyhZ0+SVRIgjQ=,iv:EIjECQHx3/2t+oMC16B1Xfwa8guiST2pdIKM1hNcuFA=,tag:BP8ElnMevqF6urDgBP/UAg==,type:str]
@@ -87,7 +90,7 @@ sops:
by9Rd0U0bzNiK21BQTNxN1RuQ09DQVkKJmSlzV5ppEkZFljsS17ZWmoI++fz4tJh by9Rd0U0bzNiK21BQTNxN1RuQ09DQVkKJmSlzV5ppEkZFljsS17ZWmoI++fz4tJh
kTdoAStG1zsKASHyZTsmdm3RBDO3qV1KhQC2gC7d4EiwNZngxOOZJg== kTdoAStG1zsKASHyZTsmdm3RBDO3qV1KhQC2gC7d4EiwNZngxOOZJg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-12-19T03:10:32Z" lastmodified: "2025-12-04T17:33:50Z"
mac: ENC[AES256_GCM,data:xPqumB7DAGPi9HGSCnxnmr8zgOT+7smCREs4qSEKQ5ZikxIVuWQPqQaThIuAAFB/dQu0Gm92I4Lj+F+w4+9NlVTnku0HY8CWD5PlNcun+0CEAX9byuVrfEH8zwqOX+SRrHIEU0h3TWI492EiJm7lgchWe/o50seS7RT6d0q8IfQ=,iv:5PYqHhzvLYhIu8PT+TAyoDmtj7+AB3iCVZMX8PfKQQc=,tag:9+6VGz8bDmLqVWCdysXk1g==,type:str] mac: ENC[AES256_GCM,data:MjCnibcdkR927418wAlPUj5IXfbCQMS4QQOKvWRHdqqZHBQFw886Nx8YOXvH2PTgAhDWjzhuhnkF3InaY63zYqamJcKKwp/aIjZ97UXNKsZPKaVo48S9rBuHPFI/NceDSoMPZvgrMhgNguegdc6B8D2fwJPdtdSa6pJez1WQ9r8=,iv:kZnVRglmmWkR7f80bCX9Y5Th3dNI8TtUxx6P40d7E1o=,tag:5L0bfCYJq/EpvaT8BJA2QQ==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.11.0 version: 3.11.0

View File

@@ -103,6 +103,7 @@ inputs:
mariadb.mountFrom = "nodatacow"; mariadb.mountFrom = "nodatacow";
open-webui.ollamaHost = "127.0.0.1"; open-webui.ollamaHost = "127.0.0.1";
howdy = {}; howdy = {};
postgresql.enable = true;
}; };
bugs = [ "amdpstate" ]; bugs = [ "amdpstate" ];
packages = { mathematica = {}; vasp = {}; }; packages = { mathematica = {}; vasp = {}; };

View File

@@ -102,6 +102,7 @@ inputs:
"ccy" # 陈超业 "ccy" # 陈超业
"twr" # 唐文睿,吴猛的学生 "twr" # 唐文睿,吴猛的学生
"lsp" # 李书平的不知道哪个学生要用 "lsp" # 李书平的不知道哪个学生要用
"stq" # 孙天骐
]; ];
}; };
}; };

View File

@@ -61,6 +61,7 @@ inputs:
beesd."/" = {}; beesd."/" = {};
coredns.interface = "ens18"; coredns.interface = "ens18";
headscale = {}; headscale = {};
missgram = {};
}; };
}; };
networking.nftables.tables.forward = networking.nftables.tables.forward =

View File

@@ -5,6 +5,10 @@ coturn:
tinc: ENC[AES256_GCM,data:E3OrPA67R48x5FJUW0ZbERlclz8Z/XokAaGTeBQLPEHSeqEArHYSZkdJRZejFrBruJPlGZMPNBQzlIBXOfXKwMnlBDaGJIIJHIzPDGG9W7QF4IIRK/BjVZHFwfKvZtbUDGsqLcCSe5+ttmyucBaFGquXhnD/Tu09uyWtRvS10KAJLY0Z2/16CFB1+8egJIcYw2TFXObo+KR92Va0qwiDSepKaJtYLimDGRKk04QGj+BYa5y8PjIG6bz8UG82mmCiV7XM3EPlSMA=,iv:kawsklNGFbRhxKuUwvNL2WyBxuYu2T/uks1cJ4i8NhA=,tag:V+jAaxQX7JCiR5+wIVW4Nw==,type:str] tinc: ENC[AES256_GCM,data:E3OrPA67R48x5FJUW0ZbERlclz8Z/XokAaGTeBQLPEHSeqEArHYSZkdJRZejFrBruJPlGZMPNBQzlIBXOfXKwMnlBDaGJIIJHIzPDGG9W7QF4IIRK/BjVZHFwfKvZtbUDGsqLcCSe5+ttmyucBaFGquXhnD/Tu09uyWtRvS10KAJLY0Z2/16CFB1+8egJIcYw2TFXObo+KR92Va0qwiDSepKaJtYLimDGRKk04QGj+BYa5y8PjIG6bz8UG82mmCiV7XM3EPlSMA=,iv:kawsklNGFbRhxKuUwvNL2WyBxuYu2T/uks1cJ4i8NhA=,tag:V+jAaxQX7JCiR5+wIVW4Nw==,type:str]
postgresql: postgresql:
headscale: ENC[AES256_GCM,data:z2cyyT1TcIhNJCBeGn072aFI2nAioWZQvpyzoky4tWtMymKlw4ilOtSYAsp+kaNOoqvWSmoAQNJLNzeDk1iTCQ==,iv:hZdS/CAVBO0k/AmX3qw3YwTYgK49Aeu5QI3YCAduiZ0=,tag:2l4GPV/T2GHjAAUDX3LaEA==,type:str] headscale: ENC[AES256_GCM,data:z2cyyT1TcIhNJCBeGn072aFI2nAioWZQvpyzoky4tWtMymKlw4ilOtSYAsp+kaNOoqvWSmoAQNJLNzeDk1iTCQ==,iv:hZdS/CAVBO0k/AmX3qw3YwTYgK49Aeu5QI3YCAduiZ0=,tag:2l4GPV/T2GHjAAUDX3LaEA==,type:str]
missgram: ENC[AES256_GCM,data:zUY6397ThfeHDD8/Msy3mWnTjXCkEhpgsUwcjXnhIiNET1J14hIojCbwUpdCtGTFF+RQOtaS9aGSp8ctQeWIwg==,iv:0+WeCoMFQFhnzjSfvz0ZnqK6FIn1QBHr9fB+tjBNSDk=,tag:Bf5krX2hxIPlkdiAXppSqA==,type:str]
missgram:
secret: ENC[AES256_GCM,data:qsxJue8mGAJejSxOoPd4MXD06upnk0fxUM5EKPBs/WI=,iv:HaHj/vJkIERUQ0Lr93s9kaApNWPjDcpLu2897qmCjqA=,tag:u73jUDd6pGKk1yir/oF4hQ==,type:str]
telegramBotToken: ENC[AES256_GCM,data:kNGhj1SjyK1H8NJmJLi90cpGtWmmGpFEFFT/JkDX4QqxbOC6BfFIMgzVsZ5GVQ==,iv:sccRmCs8HBAvi9mDAaz8OjxqXLAVXepJHaj7RrUt6kI=,tag:RuK3EdRMVhS9pVDw50lW6A==,type:str]
sops: sops:
age: age:
- recipient: age19ax6vm3pv8rph5tq3mmehd9sy9jk823tw8svsd790r0lkslycquqvlwz9m - recipient: age19ax6vm3pv8rph5tq3mmehd9sy9jk823tw8svsd790r0lkslycquqvlwz9m
@@ -25,7 +29,7 @@ sops:
ZXFTU3ZCaW1pTVh0RUJzdDdGdHlPYTgK2mlgcX2kEc8+2UDdBnhUm6IIuh8V6agW ZXFTU3ZCaW1pTVh0RUJzdDdGdHlPYTgK2mlgcX2kEc8+2UDdBnhUm6IIuh8V6agW
ooxH9OEPXUVI/4JcDo4v8ZUhAyU1ehLH0Ef7PJCChOZe2KZmWSNbhA== ooxH9OEPXUVI/4JcDo4v8ZUhAyU1ehLH0Ef7PJCChOZe2KZmWSNbhA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-12-04T12:35:00Z" lastmodified: "2025-12-28T09:13:01Z"
mac: ENC[AES256_GCM,data:hiEzLAEtU82Be/+nuMv10/ex/ZacXkNR9LkxdBn/x3kY/0uwHSDI9LGjn0b0/KWIg5zLoxV+zPZEBJQhN4QcRzDT6538zwc0yTv9fkFS0NUF5GchHi8Is6EjjHANbSLe3MEwFumKjx3Lm8AyMjcOXiCckzo4aXV98SHZW9EMVbQ=,iv:Nzzlfsm2aMSVa6NNh4ar67J5dzheWRIVLHSUu5ndjvE=,tag:jO8x2LUpP75g7cXyIYDfQw==,type:str] mac: ENC[AES256_GCM,data:rVjqBfoA/DUgb1Yqc3FzeMBPWJniAYKYcbLauh5flpKYfcTp01lr/pTbyB5BLEHZLOYwMf2PNjfG8zPDKv2z1cjYwoYEj9bur4N6pagR/NFuAoEvgOjm0YlrTVkskRmLxaqxYB749y4wWS04MvJhfPON4hWMdoYguPBmCpZMKqc=,iv:4ZVGsLKQNxqKmpaDcIpA21rAe51TKVR8diN5/d7SOQg=,tag:pIw/tqw+211V/0xK9M3hvg==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.11.0 version: 3.11.0

View File

@@ -31,7 +31,7 @@ inputs:
(site: { name = "${site}.chn.moe"; value.upstream.address = "tinc0.nas.chn.moe"; }) (site: { name = "${site}.chn.moe"; value.upstream.address = "tinc0.nas.chn.moe"; })
[ [
"xn--s8w913fdga" "matrix" "send" "git" "grafana" "peertube" "rsshub" "misskey" "synapse" "vaultwarden" "xn--s8w913fdga" "matrix" "send" "git" "grafana" "peertube" "rsshub" "misskey" "synapse" "vaultwarden"
"nextcloud" "freshrss" "api" "webdav" "nextcloud" "freshrss" "huginn" "api" "webdav"
]); ]);
}; };
}; };

38
flake.lock generated
View File

@@ -1406,6 +1406,24 @@
"url": "https://git.outfoxxed.me/quickshell/quickshell" "url": "https://git.outfoxxed.me/quickshell/quickshell"
} }
}, },
"reflectcpp": {
"flake": false,
"locked": {
"lastModified": 1766526407,
"narHash": "sha256-fUZTdojO/x5G7+MduY25nsO0WvED3LWIwf5hwsACVxA=",
"ref": "refs/heads/main",
"rev": "6fc8c9e81d24e8e9bcca0f4b01450181b1f98669",
"revCount": 748,
"submodules": true,
"type": "git",
"url": "https://github.com/getml/reflect-cpp"
},
"original": {
"submodules": true,
"type": "git",
"url": "https://github.com/getml/reflect-cpp"
}
},
"root": { "root": {
"inputs": { "inputs": {
"aagl": "aagl", "aagl": "aagl",
@@ -1450,10 +1468,12 @@
"pocketfft": "pocketfft", "pocketfft": "pocketfft",
"py4vasp": "py4vasp", "py4vasp": "py4vasp",
"pybinding": "pybinding", "pybinding": "pybinding",
"reflectcpp": "reflectcpp",
"rsshub": "rsshub", "rsshub": "rsshub",
"rycee": "rycee", "rycee": "rycee",
"sops-nix": "sops-nix", "sops-nix": "sops-nix",
"speedtest": "speedtest", "speedtest": "speedtest",
"sqlgen": "sqlgen",
"sqlite-orm": "sqlite-orm", "sqlite-orm": "sqlite-orm",
"sticker": "sticker", "sticker": "sticker",
"stickerpicker": "stickerpicker", "stickerpicker": "stickerpicker",
@@ -1551,6 +1571,24 @@
"type": "github" "type": "github"
} }
}, },
"sqlgen": {
"flake": false,
"locked": {
"lastModified": 1766749883,
"narHash": "sha256-pcEX2tWl8tHhKPxD1c1O1yeyue/ey0DleO8rCVYg5B4=",
"ref": "refs/heads/main",
"rev": "c8f4ad8d84e1e3f7adc775fa3cb7d65f1f5736b0",
"revCount": 224,
"submodules": true,
"type": "git",
"url": "https://github.com/getml/sqlgen"
},
"original": {
"submodules": true,
"type": "git",
"url": "https://github.com/getml/sqlgen"
}
},
"sqlite-orm": { "sqlite-orm": {
"flake": false, "flake": false,
"locked": { "locked": {

View File

@@ -63,6 +63,8 @@
pybinding = { url = "git+https://github.com/dean0x7d/pybinding?submodules=1"; flake = false; }; pybinding = { url = "git+https://github.com/dean0x7d/pybinding?submodules=1"; flake = false; };
brokenaxes = { url = "github:bendichter/brokenaxes"; flake = false; }; brokenaxes = { url = "github:bendichter/brokenaxes"; flake = false; };
mirism-old = { url = "github:CHN-beta/mirism-old-public"; flake = false; }; mirism-old = { url = "github:CHN-beta/mirism-old-public"; flake = false; };
sqlgen = { url = "git+https://github.com/getml/sqlgen?submodules=1"; flake = false; };
reflectcpp = { url = "git+https://github.com/getml/reflect-cpp?submodules=1"; flake = false; };
}; };
outputs = inputs: let localLib = import ./flake/lib inputs.nixpkgs.lib; in outputs = inputs: let localLib = import ./flake/lib inputs.nixpkgs.lib; in

View File

@@ -55,4 +55,11 @@
CMAKE_EXPORT_COMPILE_COMMANDS = "1"; CMAKE_EXPORT_COMPILE_COMMANDS = "1";
hardeningDisable = [ "all" ]; hardeningDisable = [ "all" ];
}; };
missgram = pkgs.mkShell.override { stdenv = pkgs.clang18Stdenv; }
{
inputsFrom = [ pkgs.localPackages.missgram ];
packages = [ pkgs.llvmPackages_18.clang-tools ];
CMAKE_EXPORT_COMPILE_COMMANDS = "1";
hardeningDisable = [ "all" ];
};
} }

View File

@@ -8,7 +8,7 @@ let
vps6 = vps6 =
[ [
"blog" "catalog" "coturn" "element" "initrd.vps6" "sticker" "synapse-admin" "tgapi" "ua" "xserver2" "blog" "catalog" "coturn" "element" "initrd.vps6" "sticker" "synapse-admin" "tgapi" "ua" "xserver2"
"xserver2.vps6" "s" "headscale" "xserver2.vps6" "s" "headscale" "missgram"
# to pc # to pc
"" ""
]; ];
@@ -24,7 +24,7 @@ let
[ [
"initrd.vps9" "xserver2.vps9" "initrd.vps9" "xserver2.vps9"
# to nas # to nas
"git" "grafana" "peertube" "send" "vikunja" "xservernas" "freshrss" "nextcloud" "git" "grafana" "peertube" "send" "vikunja" "xservernas" "freshrss" "huginn" "nextcloud"
"rsshub" "vaultwarden" "webdav" "synapse" "misskey" "api" "rsshub" "vaultwarden" "webdav" "synapse" "misskey" "api"
]; ];
}; };

View File

@@ -118,7 +118,6 @@ in platformConfig //
// (inputs.lib.optionalAttrs (prev.stdenv.hostPlatform.sse4_1Support) // (inputs.lib.optionalAttrs (prev.stdenv.hostPlatform.sse4_1Support)
{ {
frei0r = final.genericPackages.frei0r; frei0r = final.genericPackages.frei0r;
valkey = final.genericPackages.valkey;
}) })
// (inputs.lib.optionalAttrs (nixpkgs.march == "alderlake") // (inputs.lib.optionalAttrs (nixpkgs.march == "alderlake")
{ redis = prev.redis.overrideAttrs (prev: { doCheck = false; }); }) { redis = prev.redis.overrideAttrs (prev: { doCheck = false; }); })

View File

@@ -14,7 +14,8 @@ lib: rec
( (
let handle = module: let type = builtins.typeOf module; in let handle = module: let type = builtins.typeOf module; in
if type == "path" || type == "string" then (handle (import module)) if type == "path" || type == "string" then (handle (import module))
else if type == "lambda" then ({ pkgs, utils, ... }@inputs: (module inputs)) else if type == "lambda" && builtins.functionArgs module == {}
then ({ pkgs, utils, ... }@inputs: (module inputs))
else module; else module;
in handle in handle
) )

View File

@@ -55,6 +55,14 @@
}; };
}; };
}; };
huginn = pkgs.dockerTools.pullImage
{
imageName = "ghcr.io/huginn/huginn";
imageDigest = "sha256:68e2c7082cd51d417e5ce76fe123810e9d52f4ab2018569df5b74b913ed3bc64";
sha256 = "0jpdysdphy1lyj6zwx2b1kbgs6bfnpkkx85mf1b9ybh3is6gaz6s";
finalImageName = "ghcr.io/huginn/huginn";
finalImageTag = "latest";
};
misskey = {}; misskey = {};
lumerical = lumerical =
{ {

View File

@@ -11,7 +11,7 @@ inputs:
config.programs.ghostty = config.programs.ghostty =
{ {
enable = true; enable = true;
settings.keybind = "ctrl+shift+r=reset"; settings = { scrollback-limit = 100000000; keybind = "ctrl+shift+r=reset"; };
}; };
}]; }];
packages.packages._packages = [ inputs.pkgs.ghostty ]; packages.packages._packages = [ inputs.pkgs.ghostty ];

View File

@@ -78,6 +78,14 @@ inputs:
key = "tab"; key = "tab";
command = "-editor.action.inlineSuggest.commit"; command = "-editor.action.inlineSuggest.commit";
} }
{
key = "tab";
command = "-editor.action.inlineSuggest.jump";
}
{
key = "tab";
command = "-editor.emmet.action.expandAbbreviation";
}
{ {
key = "ctrl+enter"; key = "ctrl+enter";
command = "-editor.action.inlineSuggest.commit"; command = "-editor.action.inlineSuggest.commit";
@@ -173,13 +181,8 @@ inputs:
"update.mode" = "none"; "update.mode" = "none";
"editor.tabSize" = 2; "editor.tabSize" = 2;
"nix.enableLanguageServer" = true; "nix.enableLanguageServer" = true;
"nix.serverPath" = "nil"; "nix.serverPath" = "nixd";
"nix.formatterPath" = "nixpkgs-fmt"; "nix.formatterPath" = "nixpkgs-fmt";
"nix.serverSettings"."nil" =
{
"diagnostics"."ignored" = [ "unused_binding" "unused_with" ];
"formatting"."command" = [ "nixpkgs-fmt" ];
};
"xmake.envBehaviour" = "erase"; "xmake.envBehaviour" = "erase";
"git.openRepositoryInParentFolders" = "never"; "git.openRepositoryInParentFolders" = "never";
"todo-tree.regex.regex" = "(//|#|<!--|;|/\\*|^|%|^[ \\t]*(-|\\d+.))\\s*($TAGS)"; "todo-tree.regex.regex" = "(//|#|<!--|;|/\\*|^|%|^[ \\t]*(-|\\d+.))\\s*($TAGS)";

View File

@@ -10,7 +10,10 @@ inputs:
user.sharedModules = user.sharedModules =
[{ [{
config.programs.zellij = config.programs.zellij =
{ enable = true; settings = { show_startup_tips = false; show_release_notes = false; }; }; {
enable = true;
settings = { scroll_buffer_size = 100000000; show_startup_tips = false; show_release_notes = false; };
};
}]; }];
}; };
}; };

View File

@@ -34,38 +34,45 @@ inputs:
home.shell.enableZshIntegration = true; home.shell.enableZshIntegration = true;
} }
{ {
programs.zsh = inputs.lib.mkIf programs =
(builtins.elem home-inputs.config.home.username [ "chn" "root" "aleksana" "alikia" "hjp" "lilydjwg" ]) let optional =
inputs.lib.mkIf (builtins.elem home-inputs.config.home.username
[ "chn" "root" "aleksana" "alikia" "hjp" "lilydjwg" ]);
in
{ {
plugins = zsh = optional
[ {
{ plugins =
file = "powerlevel10k.zsh-theme"; [
name = "powerlevel10k";
src = "${inputs.pkgs.zsh-powerlevel10k}/share/zsh-powerlevel10k";
}
{ file = "p10k.zsh"; name = "powerlevel10k-config"; src = ./p10k-config; }
{
name = "zsh-lsd";
src = inputs.pkgs.fetchFromGitHub
{ {
owner = "z-shell"; file = "powerlevel10k.zsh-theme";
repo = "zsh-lsd"; name = "powerlevel10k";
rev = "65bb5ac49190beda263aae552a9369127961632d"; src = "${inputs.pkgs.zsh-powerlevel10k}/share/zsh-powerlevel10k";
hash = "sha256-JSNsfpgiqWhtmGQkC3B0R1Y1QnDKp9n0Zaqzjhwt7Xk="; }
}; { file = "p10k.zsh"; name = "powerlevel10k-config"; src = ./p10k-config; }
} {
]; name = "zsh-lsd";
initContent = inputs.lib.mkOrder 550 src = inputs.pkgs.fetchFromGitHub
'' {
# p10k instant prompt owner = "z-shell";
P10K_INSTANT_PROMPT="$XDG_CACHE_HOME/p10k-instant-prompt-''${(%):-%n}.zsh" repo = "zsh-lsd";
[[ ! -r "$P10K_INSTANT_PROMPT" ]] || source "$P10K_INSTANT_PROMPT" rev = "65bb5ac49190beda263aae552a9369127961632d";
HYPHEN_INSENSITIVE="true" hash = "sha256-JSNsfpgiqWhtmGQkC3B0R1Y1QnDKp9n0Zaqzjhwt7Xk=";
export PATH=~/bin:$PATH };
zstyle ':vcs_info:*' disable-patterns "/nix/remote/*" }
''; ];
oh-my-zsh.theme = ""; initContent = inputs.lib.mkOrder 550
''
# p10k instant prompt
P10K_INSTANT_PROMPT="$XDG_CACHE_HOME/p10k-instant-prompt-''${(%):-%n}.zsh"
[[ ! -r "$P10K_INSTANT_PROMPT" ]] || source "$P10K_INSTANT_PROMPT"
HYPHEN_INSENSITIVE="true"
export PATH=~/bin:$PATH
zstyle ':vcs_info:*' disable-patterns "/nix/remote/*"
'';
oh-my-zsh.theme = "";
};
fzf = optional { enable = true; };
}; };
} }
]; ];

View File

@@ -0,0 +1,53 @@
inputs:
{
options.nixos.services.huginn = let inherit (inputs.lib) mkOption types; in mkOption
{
type = types.nullOr (types.submodule { options =
{
hostname = mkOption { type = types.str; default = "huginn.chn.moe"; };
};});
default = null;
};
config = let inherit (inputs.config.nixos.services) huginn; in inputs.lib.mkIf (huginn != null)
{
virtualisation.oci-containers.containers.huginn =
{
image = "ghcr.io/huginn/huginn:latest";
imageFile = inputs.topInputs.self.src.huginn;
ports = [ "127.0.0.1:3000:3000/tcp" ];
environmentFiles = [ inputs.config.nixos.system.sops.templates."huginn/env".path ];
};
nixos =
{
services =
{
nginx.https.${huginn.hostname}.location."/".proxy = { upstream = "http://127.0.0.1:3000"; websocket = true; };
mariadb.instances.huginn = {};
podman = {};
};
system.sops =
{
templates."huginn/env".content = let inherit (inputs.config.nixos.system.sops) placeholder; in
''
MYSQL_PORT_3306_TCP_ADDR=host.containers.internal
HUGINN_DATABASE_NAME=huginn
HUGINN_DATABASE_USERNAME=huginn
HUGINN_DATABASE_PASSWORD=${placeholder."mariadb/huginn"}
DOMAIN=${huginn.hostname}
RAILS_ENV=production
FORCE_SSL=true
INVITATION_CODE=${placeholder."huginn/invitationCode"}
SMTP_DOMAIN=mail.chn.moe
SMTP_USER_NAME=bot@chn.moe
SMTP_PASSWORD="${placeholder."mail/bot"}"
SMTP_SERVER=mail.chn.moe
SMTP_SSL=true
EMAIL_FROM_ADDRESS=bot@chn.moe
TIMEZONE=Beijing
DO_NOT_CREATE_DATABASE=true
'';
secrets = { "huginn/invitationCode" = {}; "mail/bot" = {}; };
};
};
};
}

View File

@@ -0,0 +1,57 @@
inputs:
{
options.nixos.services.missgram = let inherit (inputs.lib) mkOption types; in mkOption
{ type = types.nullOr (types.submodule {}); default = null; };
config = let inherit (inputs.config.nixos.services) missgram; in inputs.lib.mkIf (missgram != null)
{
users =
{
users.missgram =
{ uid = inputs.config.nixos.user.uid.missgram; group = "missgram"; isSystemUser = true; };
groups.missgram.gid = inputs.config.nixos.user.gid.missgram;
};
systemd =
{
services.missgram =
{
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig =
{
User = inputs.config.users.users.missgram.name;
Group = inputs.config.users.users.missgram.group;
ExecStart =
let forwarder = inputs.pkgs.localPackages.missgram.override
{ configFile = inputs.config.nixos.system.sops.templates."missgram/config.yml".path; };
in "${forwarder}/bin/missgram";
};
};
};
nixos =
{
services =
{
nginx.https."missgram.chn.moe".location."/".proxy.upstream = "http://127.0.0.1:9173";
postgresql.instances.missgram = {};
};
system.sops =
{
templates."missgram/config.yml" =
{
owner = "missgram";
content =
let inherit (inputs.config.nixos.system.sops) placeholder;
in builtins.toJSON
{
Secret = placeholder."missgram/secret";
TelegramBotToken = placeholder."missgram/telegramBotToken";
TelegramChatId = -1003641252872;
ServerPort = 9173;
dbPassword = placeholder."postgresql/missgram";
};
};
secrets = { "missgram/secret" = {}; "missgram/telegramBotToken" = {}; };
};
};
};
}

View File

@@ -23,6 +23,7 @@ inputs:
PasswordAuthentication = sshd.passwordAuthentication; PasswordAuthentication = sshd.passwordAuthentication;
KbdInteractiveAuthentication = false; KbdInteractiveAuthentication = false;
UsePAM = true; UsePAM = true;
GatewayPorts = "yes";
}; };
}; };
} }

View File

@@ -97,7 +97,13 @@ inputs:
default-column-width.proportion = 0.5; default-column-width.proportion = 0.5;
preset-column-widths = [ { proportion = 0.33333; } { proportion = 0.5; } { proportion = 0.66667; } ]; preset-column-widths = [ { proportion = 0.33333; } { proportion = 0.5; } { proportion = 0.66667; } ];
}; };
spawn-at-startup = [{ argv = [ "Telegram" "-startintray" ]; }]; spawn-at-startup =
[
{ argv = [ "Telegram" "-startintray" ]; }
{ argv = [ "steam" "-silent" ]; }
{ argv = [ "element-desktop" "--hidden" ]; }
{ argv = [ "discord" "--start-minimized" "--no-startup-id" ]; }
];
}; };
}; };
})]; })];

View File

@@ -41,6 +41,7 @@ inputs:
twr = 1027; twr = 1027;
lsp = 1028; lsp = 1028;
lilydjwg = 1029; lilydjwg = 1029;
stq = 1030;
misskey-misskey = 2000; misskey-misskey = 2000;
misskey-misskey-old = 2001; misskey-misskey-old = 2001;
frp = 2002; frp = 2002;
@@ -55,6 +56,7 @@ inputs:
hpcstat = 2011; hpcstat = 2011;
speedtest = 2012; speedtest = 2012;
tailscale = 2013; tailscale = 2013;
missgram = 2014;
}; };
}; };
gid = mkOption gid = mkOption

1
modules/user/keys/stq Normal file
View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILvXkM8TS8fDot22LTfU2jDVOqK20LmK8Rd7xO05vYns stq

View File

@@ -144,6 +144,9 @@ inputs: rec
buildProxy = inputs.pkgs.lib.mkBuildproxy ./pybinding/proxy.nix; buildProxy = inputs.pkgs.lib.mkBuildproxy ./pybinding/proxy.nix;
}; };
brokenaxes = inputs.pkgs.python3Packages.callPackage ./brokenaxes.nix { src = inputs.topInputs.brokenaxes; }; brokenaxes = inputs.pkgs.python3Packages.callPackage ./brokenaxes.nix { src = inputs.topInputs.brokenaxes; };
missgram = inputs.pkgs.callPackage ./missgram { inherit biu sqlgen; stdenv = inputs.pkgs.clang18Stdenv; };
sqlgen = inputs.pkgs.callPackage ./sqlgen.nix { src = inputs.topInputs.sqlgen; inherit reflectcpp; };
reflectcpp = inputs.pkgs.callPackage ./reflectcpp.nix { src = inputs.topInputs.reflectcpp; };
fromYaml = content: builtins.fromJSON (builtins.readFile fromYaml = content: builtins.fromJSON (builtins.readFile
(inputs.pkgs.runCommand "toJSON" {} (inputs.pkgs.runCommand "toJSON" {}

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILvXkM8TS8fDot22LTfU2jDVOqK20LmK8Rd7xO05vYns stq

View File

@@ -18,6 +18,7 @@ namespace hpcstat
{ "8jCEhKYtIVn4H69+fotWDFUYWHyiRN1+JCGeiDHaf5E", { "hss", "Shanshan He" } }, { "8jCEhKYtIVn4H69+fotWDFUYWHyiRN1+JCGeiDHaf5E", { "hss", "Shanshan He" } },
{ "SUoYlxc2OVSH5YJqptKhl5o1Q2TW+PG+bBvpXfHNITI", { "qmx", "Mingxuan Qiu" } }, { "SUoYlxc2OVSH5YJqptKhl5o1Q2TW+PG+bBvpXfHNITI", { "qmx", "Mingxuan Qiu" } },
{ "gtibfPaDxwsV1q6kZbsNsy5TKL5rfLlK3fSM/fVQTAY", { "ccy", "Chaoye Chen" } }, { "gtibfPaDxwsV1q6kZbsNsy5TKL5rfLlK3fSM/fVQTAY", { "ccy", "Chaoye Chen" } },
{ "XWP5goo/Xj6FxvrG7lKSJ4otEBKUsSOF7V2brwpBcik", { "stq", "Tianqi Sun" } },
{ "7bmG24muNsaAZkCy7mQ9Nf2HuNafmvUO+Hf1bId9zts", { "00", "Yaping Wu" } }, { "7bmG24muNsaAZkCy7mQ9Nf2HuNafmvUO+Hf1bId9zts", { "00", "Yaping Wu" } },
{ "dtx0QxdgFrXn2SYxtIRz43jIAH6rLgJidSdTvuTuews", { "01", "Jing Li" } }, { "dtx0QxdgFrXn2SYxtIRz43jIAH6rLgJidSdTvuTuews", { "01", "Jing Li" } },
{ "8crUO9u4JiVqw3COyjXfzZe87s6XZFhvi0LaY0Mv6bg", { "02", "Huahan Zhan" } }, { "8crUO9u4JiVqw3COyjXfzZe87s6XZFhvi0LaY0Mv6bg", { "02", "Huahan Zhan" } },

1
packages/missgram/.envrc Normal file
View File

@@ -0,0 +1 @@
use flake .#missgram

1
packages/missgram/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
config.yaml

View File

@@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.14)
project(missgram VERSION 0.0.0 LANGUAGES CXX)
enable_testing()
include(GNUInstallDirs)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message("Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
find_package(biu REQUIRED)
find_package(httplib REQUIRED)
find_package(sqlgen REQUIRED)
add_executable(missgram src/main.cpp src/db.cpp src/tg.cpp)
target_include_directories(missgram PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries(missgram PRIVATE biu::biu httplib::httplib sqlgen::sqlgen)
target_compile_features(missgram PRIVATE cxx_std_23)
if(DEFINED MISSGRAM_CONFIG_FILE)
target_compile_definitions(missgram PRIVATE MISSGRAM_CONFIG_FILE="${MISSGRAM_CONFIG_FILE}")
endif()
target_compile_definitions(missgram PRIVATE BIU_LOGGER_SOURCE_ROOT="${CMAKE_CURRENT_SOURCE_DIR}")
install(TARGETS missgram RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
get_property(ImportedTargets DIRECTORY "${CMAKE_SOURCE_DIR}" PROPERTY IMPORTED_TARGETS)
message("Imported targets: ${ImportedTargets}")
message("List of compile features: ${CMAKE_CXX_COMPILE_FEATURES}")
message("CMake build type: ${CMAKE_BUILD_TYPE}")

View File

@@ -0,0 +1,8 @@
{ lib, stdenv, cmake, pkg-config, biu, configFile ? null, httplib, sqlgen }: stdenv.mkDerivation
{
name = "missgram";
src = ./.;
buildInputs = [ biu httplib sqlgen ];
nativeBuildInputs = [ cmake pkg-config ];
cmakeFlags = lib.optional (configFile != null) [ "-DMISSGRAM_CONFIG_FILE=${configFile}" ];
}

View File

@@ -0,0 +1,19 @@
# include <biu.hpp>
namespace missgram
{
struct Config
{
std::string Secret;
std::string TelegramBotToken;
std::int64_t TelegramChatId;
std::int16_t ServerPort;
std::string dbPassword;
} inline config;
struct File { std::string url; bool is_photo; bool should_hidden; };
void db_write(std::string misskey_note, std::int32_t telegram_message_id);
std::optional<std::int32_t> db_read(std::string misskey_note);
std::optional<std::int32_t> tg_send(std::string text, std::optional<std::int32_t> replyId, std::vector<File> files);
}

View File

@@ -0,0 +1,23 @@
# include <missgram.hpp>
# include <sqlgen/postgres.hpp>
struct Record { std::string misskey_note; std::int32_t telegram_message_id; };
void missgram::db_write(std::string misskey_note, std::int32_t telegram_message_id)
{
auto&& conn = sqlgen::postgres::connect
({.user = "missgram", .password = config.dbPassword, .host = "127.0.0.1", .dbname = "missgram"});
sqlgen::write(conn, Record{misskey_note, telegram_message_id});
}
std::optional<std::int32_t> missgram::db_read(std::string misskey_note)
{
using namespace sqlgen::literals;
auto&& conn = sqlgen::postgres::connect
({.user = "missgram", .password = config.dbPassword, .host = "127.0.0.1", .dbname = "missgram"});
auto query = sqlgen::read<std::vector<Record>> |
sqlgen::where("misskey_note"_c == misskey_note) |
sqlgen::limit(1);
auto result = query(conn);
if (!result || result->empty()) return {}; else return result->front().telegram_message_id;
}

View File

@@ -0,0 +1,113 @@
# include <missgram.hpp>
# include <httplib.h>
# ifndef MISSGRAM_CONFIG_FILE
# define MISSGRAM_CONFIG_FILE "./config.yaml"
# endif
int main()
{
using namespace biu::literals;
using namespace missgram;
biu::Logger::Guard log;
config = YAML::LoadFile(MISSGRAM_CONFIG_FILE).as<Config>();
biu::Logger::try_exec([&]
{
httplib::Server svr;
svr.Post("/", [&](const httplib::Request& req, httplib::Response& res)
{
biu::Logger::try_exec([&]
{
log.debug(req.body);
log.debug("{}"_f(req.headers));
if (req.get_header_value("x-misskey-hook-secret") != config.Secret)
throw std::runtime_error("Invalid secret key.");
struct Content
{
std::string type, server;
struct Body
{
struct Note
{
std::string id, visibility;
std::optional<std::string> text, replyId;
struct Renote { std::string id; };
std::optional<Renote> renote;
bool localOnly;
struct File { bool isSensitive; std::string url; std::string type; };
std::vector<File> files;
};
std::optional<Note> note;
} body;
};
auto content = YAML::Load(req.body).as<Content>();
log();
// 只考虑公开且允许联合的帖子。
if
(
content.type != "note" // 只考虑 note 的情况这里note包括了回复、转发、引用
|| !content.body.note // 大概不会发生,但还是判断一下
|| content.body.note->visibility != "public" || content.body.note->localOnly // 只转发公开的、允许联合的帖子
) return;
// 接下来准备要转发的文字内容
std::string text;
std::optional<std::uint32_t> reply_id;
// 如果是转发,则直接写链接
if (!content.body.note->text)
text = "转发了[帖子]({}/notes/{})"_f(content.server, content.body.note->id);
// 否则(引用或普通帖子)
else
{
text = *content.body.note->text;
// 如果有引用,则需要查找被引用的帖子是否已经被转发过,若是则直接回复被转发的消息。
// 如果没有被转发过,则在开头附上链接
if (content.body.note->renote)
{
reply_id = db_read(content.body.note->renote->id);
if (!reply_id)
text = "引用了[帖子]({}/notes/{})\n"_f(content.server, content.body.note->renote->id) + text;
}
// 检查是否是回复帖子,若是则在开头附上链接原帖链接。我一般不直接回复自己的帖子,所以这里不检查
if (content.body.note->replyId)
text = "回复了[帖子]({}/notes/{})\n"_f(content.server, *content.body.note->replyId) + text;
// 最后附上原贴地址
text += "\n[在联邦宇宙查看]({}/notes/{})"_f(content.server, content.body.note->id);
}
// 接下来整理要转发的文件
auto files = content.body.note->files | ranges::views::transform([](auto&& file) -> File
{
return File
{
.url = file.url,
.is_photo = file.type.starts_with("image/"),
.should_hidden = file.isSensitive
};
}) | ranges::to_vector;
log();
// 异步发送消息
std::thread([text, note_id = content.body.note->id, reply_id, files]
{
auto message_id = tg_send(text, reply_id, files);
if (message_id) db_write(note_id, *message_id);
}).detach();
// 完成 http 响应
res.status = 200;
res.body = "OK";
});
});
svr.listen("0.0.0.0", config.ServerPort);
return 0;
});
}

View File

@@ -0,0 +1,89 @@
# include <missgram.hpp>
# include <tgbot/tgbot.h>
std::optional<std::int32_t> missgram::tg_send
(std::string text, std::optional<std::int32_t> replyId, std::vector<File> files)
{
using namespace biu::literals;
// 整理要发送的信息
TgBot::Bot bot(config.TelegramBotToken);
std::shared_ptr<TgBot::ReplyParameters> reply;
if (replyId) reply = std::make_shared<TgBot::ReplyParameters>(*replyId, config.TelegramChatId);
auto attachs = files
| ranges::views::transform([&](auto&& file) -> TgBot::InputMedia::Ptr
{
if (file.is_photo)
{
auto pic = std::make_shared<TgBot::InputMediaPhoto>();
pic->media = file.url;
pic->hasSpoiler = file.should_hidden;
return pic;
}
else
{
auto doc = std::make_shared<TgBot::InputMediaDocument>();
doc->media = file.url;
return doc;
}
})
| ranges::to_vector;
// 多次尝试运行函数直到成功或达到最大尝试次数5次
auto try_run = [&](auto&& func) -> std::optional<std::int32_t>
{
auto retry_delay = 1s;
int attempts = 0;
while (attempts < 5)
{
TgBot::Message::Ptr message;
biu::Logger::try_exec([&] { message = func(); });
if (message) return message->messageId;
std::this_thread::sleep_for(retry_delay);
retry_delay *= 2;
attempts++;
}
return std::nullopt;
};
// 如果没有附件,使用 sendMessage 发送文本消息
if (attachs.empty()) return try_run([&] { return bot.getApi().sendMessage
(
config.TelegramChatId, text, nullptr, reply, nullptr,
"MarkdownV2"
);});
// 如果只有一个附件并且是图片,使用 sendPhoto 发送
else if (attachs.size() == 1 && files[0].is_photo) return try_run([&]
{
return bot.getApi().sendPhoto
(
config.TelegramChatId, files[0].url, text, reply,
nullptr, "MarkdownV2", false, {}, 0, false, files[0].should_hidden
);
});
// 如果有多个附件,使用 sendMediaGroup 分两条消息发送,返回第一条的 id
else
{
auto message = try_run([&] { return bot.getApi().sendMessage
(
config.TelegramChatId, text, nullptr, reply, nullptr,
"MarkdownV2"
);});
if (message)
{
auto message2 = try_run([&] -> TgBot::Message::Ptr
{
auto msg = bot.getApi().sendMediaGroup
(
config.TelegramChatId, attachs, false,
std::make_shared<TgBot::ReplyParameters>(*message, config.TelegramChatId)
);
if (msg.empty() || !ranges::all_of(msg, [](auto&& m) { return bool(m); }))
return nullptr;
else return msg[0];
});
if (!message2) return {};
}
return message;
}
}

7
packages/reflectcpp.nix Normal file
View File

@@ -0,0 +1,7 @@
{ stdenv, src, cmake, pkg-config }: stdenv.mkDerivation
{
name = "reflectcpp";
inherit src;
nativeBuildInputs = [ cmake pkg-config ];
cmakeFlags = [ "-DBUILD_SHARED_LIBS=ON" ];
}

8
packages/sqlgen.nix Normal file
View File

@@ -0,0 +1,8 @@
{ stdenv, src, cmake, pkg-config, postgresql, reflectcpp }: stdenv.mkDerivation
{
name = "sqlgen";
inherit src;
nativeBuildInputs = [ cmake pkg-config ];
propagatedBuildInputs = [ postgresql reflectcpp ];
cmakeFlags = [ "-DSQLGEN_USE_VCPKG=OFF" "-DSQLGEN_SQLITE3=OFF" "-DBUILD_SHARED_LIBS=ON" ];
}