mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-23 17:56:49 +00:00
Compare commits
825 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
607b380ddd | ||
|
|
1ec9118af2 | ||
|
|
c911ad45bf | ||
|
|
0dee3e311a | ||
|
|
17ef5e3aee | ||
|
|
1505e2dbd4 | ||
|
|
1ea5913f3d | ||
|
|
7f548a1982 | ||
|
|
d1b7133db3 | ||
|
|
c5bee672d1 | ||
|
|
50b054890a | ||
|
|
ef9d269660 | ||
|
|
f01b0d6641 | ||
|
|
f9519141b1 | ||
|
|
1b626caa53 | ||
|
|
4167b6be54 | ||
|
|
8305ba92c3 | ||
|
|
8efe6d7f70 | ||
|
|
8cd9587ab7 | ||
|
|
ed0da062df | ||
|
|
83daa09c80 | ||
|
|
5599bf179b | ||
|
|
44cf96ce70 | ||
|
|
540408a3d0 | ||
|
|
9058898f3b | ||
|
|
4643529e7f | ||
|
|
b0f9268996 | ||
|
|
b863a7e523 | ||
|
|
4a77c987ed | ||
|
|
7d7c4ba3a5 | ||
|
|
f2e8fd0ec4 | ||
|
|
a8f1cef5b8 | ||
|
|
7c481de811 | ||
|
|
b66d883c1c | ||
|
|
48a742add5 | ||
|
|
adddc1b5ba | ||
|
|
d63ef5e58c | ||
|
|
765651d94d | ||
|
|
8c9462d387 | ||
|
|
04bfe96e16 | ||
|
|
2f8ef39ead | ||
|
|
35cdfbf169 | ||
|
|
fd69303a0e | ||
|
|
271311eeaf | ||
|
|
00b2b24e54 | ||
|
|
c8e6b9efa5 | ||
|
|
b22f2f6420 | ||
|
|
fa5c65f927 | ||
|
|
98f29b485b | ||
|
|
712a38c70f | ||
|
|
c4dc037b3b | ||
|
|
6dddaa5992 | ||
|
|
8879ed71c5 | ||
|
|
b4c4f73e5e | ||
|
|
17e64803c6 | ||
|
|
9c3b354fa2 | ||
|
|
040caa1f40 | ||
|
|
4cd8a7cb46 | ||
|
|
782b54ac33 | ||
|
|
6437575763 | ||
|
|
df8856454a | ||
|
|
132f47d86f | ||
|
|
07f8dc543f | ||
|
|
9a2fd8c91d | ||
|
|
6867f69909 | ||
|
|
2c80f35388 | ||
|
|
4e855011bc | ||
|
|
a46dd753ba | ||
|
|
d7f3a0bf7e | ||
|
|
411c49addd | ||
|
|
6bc29e8c3f | ||
|
|
4b3224a748 | ||
|
|
1b95433cb6 | ||
|
|
64db3f4c09 | ||
|
|
22509fed14 | ||
|
|
819b5f3dbf | ||
|
|
2c1975d203 | ||
|
|
46d6aa44d1 | ||
|
|
17130b7215 | ||
|
|
3b0d0e033f | ||
|
|
def6b6751b | ||
|
|
90756bde27 | ||
|
|
a28c431dcd | ||
|
|
50fc619d92 | ||
|
|
2475c040b9 | ||
|
|
d166e198de | ||
|
|
5a9750a4b6 | ||
|
|
fc64511268 | ||
|
|
f2b8897ed1 | ||
|
|
dae03afc2d | ||
|
|
5d383dcae6 | ||
|
|
3e4c7ac9f8 | ||
|
|
f48caa08e9 | ||
|
|
f32fafdf15 | ||
|
|
f427b89617 | ||
|
|
b0e36948c5 | ||
|
|
b0254aea2d | ||
|
|
a84b9ca395 | ||
|
|
1a9f2a23c4 | ||
|
|
e6cb7ceb7b | ||
|
|
ec28ae562b | ||
|
|
74b832ea4e | ||
|
|
32c107ae53 | ||
|
|
87d28aea81 | ||
|
|
79b81ac5d1 | ||
|
|
57489bc9cb | ||
|
|
e45b09b675 | ||
|
|
c3d579a835 | ||
|
|
9d2f4fd795 | ||
|
|
a173c84ffb | ||
|
|
94ed85914a | ||
|
|
90c2986277 | ||
|
|
3cff63193d | ||
|
|
53066b1f14 | ||
|
|
c7524af07a | ||
|
|
500a148632 | ||
|
|
33c9aeda21 | ||
|
|
9b40ab3b52 | ||
|
|
5a115f1822 | ||
|
|
de9900ad14 | ||
|
|
731fbca87c | ||
|
|
8ed27013a4 | ||
|
|
9590afa752 | ||
|
|
f534997e0e | ||
|
|
d609a68dc4 | ||
|
|
92456aa838 | ||
|
|
d074f47659 | ||
|
|
4cc16897cf | ||
|
|
8cabec1aff | ||
|
|
e7650ab10e | ||
|
|
97ecba07bb | ||
|
|
061413303a | ||
|
|
6bb3d4b48a | ||
|
|
90a27b2a4d | ||
|
|
61aa656611 | ||
|
|
c6ae45f6ab | ||
|
|
d72eb0b06d | ||
|
|
5c728127f1 | ||
|
|
a64472188c | ||
|
|
39f7f0a1c6 | ||
|
|
1e3461918e | ||
|
|
ae0704e2bb | ||
|
|
42e07c2445 | ||
|
|
641cf5a350 | ||
|
|
f984a9122e | ||
|
|
889795a326 | ||
|
|
d5df9e0af9 | ||
|
|
b7a6cc5158 | ||
|
|
55d49f87ff | ||
|
|
c2abbf0fc0 | ||
|
|
ba11952945 | ||
|
|
a7f2556b48 | ||
|
|
b66dd2c01b | ||
|
|
c6261af03c | ||
|
|
e44d1ac62e | ||
|
|
37afe1959a | ||
|
|
da04f6b100 | ||
|
|
168dc5cb35 | ||
|
|
9f4d5df8d2 | ||
|
|
0c21c223be | ||
|
|
1fc4ac8e07 | ||
|
|
088161e9ba | ||
|
|
246429f7a1 | ||
|
|
2478dd6c10 | ||
|
|
ee234001f1 | ||
|
|
9325959358 | ||
|
|
aed6784f55 | ||
|
|
b5f916dbac | ||
|
|
2555623064 | ||
|
|
83aa57a764 | ||
|
|
44ed1b1547 | ||
|
|
1b91674f9b | ||
|
|
cc363c2f51 | ||
|
|
0982943799 | ||
|
|
c79faf6c0e | ||
|
|
ea110d5da9 | ||
|
|
40dc70e8c7 | ||
|
|
5cc684f4b6 | ||
|
|
3f605d59d4 | ||
|
|
d79af97dfc | ||
|
|
a701e14a62 | ||
|
|
8e30183d7c | ||
|
|
7d21795c2f | ||
|
|
26765f31f7 | ||
|
|
708c523b57 | ||
|
|
d05c6b996c | ||
|
|
f2f83b0a60 | ||
|
|
2c0e14fb55 | ||
|
|
dca2e6f060 | ||
|
|
440e43935a | ||
|
|
1dff9a48a8 | ||
|
|
85e90bb8d5 | ||
|
|
b62b2382fd | ||
|
|
07f64a0107 | ||
|
|
dcdb2cb175 | ||
|
|
33e7ae83dc | ||
|
|
ac0a1da140 | ||
|
|
1ad03ac61c | ||
|
|
b28736cb84 | ||
|
|
602c01e2d9 | ||
|
|
7b65c1aeb7 | ||
|
|
a27973800c | ||
|
|
cb4580c0d9 | ||
|
|
1a74d83eae | ||
|
|
319ee49c67 | ||
|
|
cefa3e1e1e | ||
|
|
061e61b740 | ||
|
|
73d756f211 | ||
|
|
3bb83610b8 | ||
|
|
8e85b87764 | ||
|
|
4d0f5a56ed | ||
|
|
a8359e3e00 | ||
|
|
3812331901 | ||
|
|
1714bd26f9 | ||
|
|
d8ad42f760 | ||
|
|
c477bd2bae | ||
|
|
aa1cd98646 | ||
|
|
5f545a9bbc | ||
|
|
0d3bc2cf47 | ||
|
|
8e65142d4c | ||
|
|
c26a758825 | ||
|
|
a02d8cee86 | ||
|
|
2c4d2981cd | ||
|
|
6c5e0a20f1 | ||
|
|
db920da4b8 | ||
|
|
efdc3eb7bb | ||
|
|
c0da86e4ca | ||
|
|
720a24e9ad | ||
|
|
7dc6096e07 | ||
|
|
7910205674 | ||
|
|
1fbc51d02b | ||
|
|
a3d968c6af | ||
|
|
63c61f8e47 | ||
|
|
1ae59f4229 | ||
|
|
4a95a6928b | ||
|
|
54a092a822 | ||
|
|
9898d47db4 | ||
|
|
b46e55c57b | ||
|
|
cb6f9f3e00 | ||
|
|
d750ba5f99 | ||
|
|
c84db87532 | ||
|
|
3da662ef61 | ||
|
|
2f42c75df7 | ||
|
|
14388487fd | ||
|
|
a155748f88 | ||
|
|
c7fa69a25b | ||
|
|
5194cb103a | ||
|
|
77ec0d1c78 | ||
|
|
d85c9a3c0a | ||
|
|
97a8e6f5c2 | ||
|
|
3d73b42c15 | ||
|
|
4156dfcd4e | ||
|
|
9fb19bffc1 | ||
|
|
fe1cdce59d | ||
|
|
c07caf6be8 | ||
|
|
cab8c60fcb | ||
|
|
023c7da52b | ||
|
|
6b2bcbee6e | ||
|
|
ebac577ede | ||
|
|
0846291779 | ||
|
|
fab9d95096 | ||
|
|
2dc853ebfc | ||
|
|
5867a351a8 | ||
|
|
5605e9a666 | ||
|
|
337b720d31 | ||
|
|
06185d5f7d | ||
|
|
90cfdd140b | ||
|
|
5a41d559a3 | ||
|
|
b6805a94a3 | ||
|
|
6a678cd5a9 | ||
|
|
ecaf61252a | ||
|
|
85c4e4ac37 | ||
|
|
16394182b2 | ||
|
|
a0cc53cbb7 | ||
|
|
f331ee2c24 | ||
|
|
cb0767f28e | ||
|
|
91aaf3be19 | ||
|
|
9540e564fc | ||
|
|
2100d6287c | ||
|
|
8ad8183d4f | ||
|
|
90f2d93768 | ||
|
|
bae8dc330c | ||
|
|
599ca4d2c9 | ||
|
|
ff7a1e7c0e | ||
|
|
216cd51c4a | ||
|
|
568e9935ac | ||
|
|
28e9247c9a | ||
|
|
df3f16d424 | ||
|
|
41d03a15ac | ||
|
|
3f0e67075f | ||
|
|
67329ec668 | ||
|
|
f28d783272 | ||
|
|
2c9d015f38 | ||
|
|
5ad8a93d48 | ||
|
|
ac9c1504e9 | ||
|
|
4cde913453 | ||
|
|
f05d041e6d | ||
|
|
ce4b41ee73 | ||
|
|
0c3c4c08ea | ||
|
|
67d9486495 | ||
|
|
bd00911f85 | ||
|
|
4cb3123ff6 | ||
|
|
4ff1411c38 | ||
|
|
f983a2eab2 | ||
|
|
fd7c86c2da | ||
|
|
d90aa1798b | ||
|
|
afa602f940 | ||
|
|
773698a0d4 | ||
|
|
08907e8953 | ||
|
|
332e9a53d7 | ||
|
|
7a8e2091a6 | ||
|
|
3ed05b8e26 | ||
|
|
d3dbfc5e9e | ||
|
|
30c84efb57 | ||
|
|
3ba8602156 | ||
|
|
9d2aacab58 | ||
|
|
c7b9751e0e | ||
|
|
9cfbc35ac4 | ||
|
|
ba618dc2b6 | ||
|
|
f3c870b8c7 | ||
|
|
46ec3e51b0 | ||
|
|
4ca93c3c45 | ||
|
|
7ab499e2c0 | ||
|
|
102f3de120 | ||
|
|
01fd6f3ad6 | ||
|
|
cca465d30d | ||
|
|
dc7f2acc50 | ||
|
|
79a15ad781 | ||
|
|
4e6905d562 | ||
|
|
03a5853a91 | ||
|
|
f3fae74bde | ||
|
|
8bbff388d2 | ||
|
|
40d5fe75e7 | ||
|
|
cdbabc0a0b | ||
|
|
97ecfc03c8 | ||
|
|
70d35bfeb8 | ||
|
|
a11866c544 | ||
|
|
5aaf5476e0 | ||
|
|
7e78922056 | ||
|
|
e7dad02c63 | ||
|
|
da5fb391a4 | ||
|
|
3b48b79997 | ||
|
|
30e887a85b | ||
|
|
c737c792f6 | ||
|
|
64f4853b13 | ||
|
|
0c890e590c | ||
|
|
b664b85495 | ||
|
|
3894a6a2d1 | ||
|
|
ae8224b734 | ||
|
|
bd5739d7a0 | ||
|
|
3a8a8efbd1 | ||
|
|
4fc1f4c60e | ||
|
|
079bbc8e78 | ||
|
|
70bfbd7d8e | ||
|
|
f0c7222055 | ||
|
|
7b1b3d4d8e | ||
|
|
7d6b4b7a23 | ||
|
|
a4d0b7d1cb | ||
|
|
62e786b9b8 | ||
|
|
38ae309285 | ||
|
|
f87b63d6ee | ||
|
|
3b3f1caf84 | ||
|
|
724be4c1cf | ||
|
|
b4ab287994 | ||
|
|
19d17940c0 | ||
|
|
aa46079ed4 | ||
|
|
5e81e3a6a6 | ||
|
|
e2f2b6aa5d | ||
|
|
a7c67b04ca | ||
|
|
465207034d | ||
|
|
93b9cf4b76 | ||
|
|
dc57860f0d | ||
|
|
f71b0bc945 | ||
|
|
1c9132627b | ||
|
|
b14d5de641 | ||
|
|
530743cf97 | ||
|
|
d1ab859621 | ||
|
|
fe76ada8d0 | ||
|
|
e096f4f081 | ||
|
|
0d8f7b854d | ||
|
|
b9beb6ec16 | ||
|
|
7afcf82c32 | ||
|
|
b27dd345af | ||
|
|
9fdf8c6a75 | ||
|
|
1010f270a0 | ||
|
|
0db051a251 | ||
|
|
890a431e24 | ||
|
|
173e0ea157 | ||
|
|
4c99ce4ab2 | ||
|
|
6f98228c41 | ||
|
|
95d15aa107 | ||
|
|
2f09e74f1a | ||
|
|
f30fcb3941 | ||
|
|
06254a9afc | ||
|
|
fd95c6cac7 | ||
|
|
2196bccda5 | ||
|
|
b0ac2b4147 | ||
|
|
5322321944 | ||
|
|
2f951e0ef6 | ||
|
|
1e6dcc88d2 | ||
|
|
8bbcfc40dc | ||
|
|
811ea46523 | ||
|
|
c37e54cf9b | ||
|
|
4c095e8eb5 | ||
|
|
c580ec7b92 | ||
|
|
0c45d3c5ba | ||
|
|
2bc8a4cefd | ||
|
|
92d28adb07 | ||
|
|
cc2b1dbbaa | ||
|
|
bd98cadab3 | ||
|
|
c417f88e3b | ||
|
|
b26a9af49b | ||
|
|
e4b00b35f2 | ||
|
|
11bab46b8b | ||
|
|
7eb24d7bd6 | ||
|
|
9a26366ff8 | ||
|
|
0058bc6fa5 | ||
|
|
ca3f3e0cab | ||
|
|
cf51ca454d | ||
|
|
35c3c2a2b3 | ||
|
|
12bb61c23d | ||
|
|
2e5a2a1393 | ||
|
|
4259bb088e | ||
|
|
0768765f21 | ||
|
|
dc7ee7fadc | ||
|
|
7665a1c339 | ||
|
|
6015cd5cb7 | ||
|
|
08aa8f2136 | ||
|
|
c27e447f57 | ||
|
|
9f1a3a0304 | ||
|
|
7714478fdc | ||
|
|
91bca33a54 | ||
|
|
c67b967817 | ||
|
|
150ed2c733 | ||
|
|
1c23e4b5b3 | ||
|
|
77c4dee6a8 | ||
|
|
d6fe8eec38 | ||
|
|
c12d83bbf0 | ||
|
|
0e6b75aa5c | ||
|
|
dd1dfdcf34 | ||
|
|
792d8dab34 | ||
|
|
4f23434f81 | ||
|
|
7797c4e0b0 | ||
|
|
6463a2be2d | ||
|
|
972a46ac2e | ||
|
|
db3091b21b | ||
|
|
476733ca19 | ||
|
|
d0c302c1f1 | ||
|
|
164deb1096 | ||
|
|
b39ea679e7 | ||
|
|
062a5f470c | ||
|
|
48fb388da2 | ||
|
|
a23cdc9605 | ||
|
|
1c7eb0f5a1 | ||
|
|
58050c9ec3 | ||
|
|
5908cc40a8 | ||
|
|
bffb5e53bf | ||
|
|
4a0b79f1a1 | ||
|
|
3ddb77e9f8 | ||
|
|
16f7bccb11 | ||
|
|
ecec5cdde2 | ||
|
|
cf4fca9836 | ||
|
|
e5d61b2796 | ||
|
|
fc493ea510 | ||
|
|
7983dc01f1 | ||
|
|
09f914cecd | ||
|
|
9968b0ac36 | ||
|
|
969a5f711c | ||
|
|
ccb4601c85 | ||
|
|
25aabe7553 | ||
|
|
13755d4d06 | ||
|
|
1d6e87d103 | ||
|
|
8673ef8420 | ||
|
|
ab1fb70f4c | ||
|
|
31fe6923ff | ||
|
|
0b07b7c4a7 | ||
|
|
0abe05b7bd | ||
|
|
45ff19f9ae | ||
|
|
d25883ff1b | ||
|
|
d2f43e4e50 | ||
|
|
792167a71c | ||
|
|
f2586d7cb0 | ||
|
|
c37846b4cd | ||
|
|
17c4ec6790 | ||
|
|
7023040882 | ||
|
|
8c38de1b26 | ||
|
|
1917c9da95 | ||
|
|
668bf5009b | ||
|
|
e9ca1e3537 | ||
|
|
ebdb412adf | ||
|
|
e73c72d148 | ||
|
|
d1d843c583 | ||
|
|
464e375529 | ||
|
|
2b12f8a294 | ||
|
|
b305e98519 | ||
|
|
5431e49c2a | ||
|
|
6098cdc31d | ||
|
|
308d7c2c1c | ||
|
|
454f40ffb9 | ||
|
|
dd3b3dec33 | ||
|
|
bc2831c066 | ||
|
|
905d2acdbd | ||
|
|
54c2b6b6d5 | ||
|
|
b6a4ccac7f | ||
|
|
3fce1cc934 | ||
|
|
375a888a37 | ||
|
|
0d62034f32 | ||
|
|
f7d722aaf0 | ||
|
|
56759bc710 | ||
|
|
d27b5c28ef | ||
|
|
a0d1cada54 | ||
|
|
ca7e1da585 | ||
|
|
5f097c4002 | ||
|
|
203dc6daf6 | ||
|
|
e895850f17 | ||
|
|
f776e7947c | ||
|
|
416ec920cb | ||
|
|
b5da72eb40 | ||
|
|
3dde77608e | ||
|
|
a0407553ec | ||
|
|
8d594fe0b6 | ||
|
|
e68e87d388 | ||
|
|
4cabd42c0b | ||
|
|
df33f7d0fc | ||
|
|
d6b5e3981c | ||
|
|
6aa0300c85 | ||
|
|
264ca84513 | ||
|
|
816306872d | ||
|
|
13aced705a | ||
|
|
95d0f879ca | ||
|
|
f37d2297bb | ||
|
|
0d90a53b8e | ||
|
|
f91dfe7efa | ||
|
|
ec757e3ef8 | ||
|
|
3b2ca10b05 | ||
|
|
b438e38268 | ||
|
|
bb405f2824 | ||
|
|
1d640fbec0 | ||
|
|
ecc820333e | ||
|
|
9cc227aa61 | ||
|
|
93420eebc0 | ||
|
|
6014b3bdc6 | ||
|
|
81789c717f | ||
|
|
dfa6330821 | ||
|
|
1d5d9c12a7 | ||
|
|
2cbbbe7359 | ||
|
|
4706cedbf9 | ||
|
|
a11b955a9d | ||
|
|
e1366f6267 | ||
|
|
6bff839821 | ||
|
|
0b37acf16e | ||
|
|
70c39eef0a | ||
|
|
1988b18053 | ||
|
|
67f87396e8 | ||
|
|
3734721c58 | ||
|
|
0f6a3f2ec8 | ||
|
|
ab9ca4b9c3 | ||
|
|
c05cffbd88 | ||
|
|
0e3f3d1143 | ||
|
|
ff02a4a8d4 | ||
|
|
c8c35b5bf7 | ||
|
|
18daa6a8c7 | ||
|
|
c95b58852c | ||
|
|
80ccceb9b0 | ||
|
|
eaa308d3ce | ||
|
|
d05ac7e10d | ||
|
|
a80aef16a0 | ||
|
|
338560fedb | ||
|
|
632830278f | ||
|
|
8b614bd3c4 | ||
|
|
657354c2e8 | ||
|
|
7a0d9f2325 | ||
|
|
ae45c0c7ae | ||
|
|
c3b0e31a0a | ||
|
|
f7207c1326 | ||
|
|
9a9817c6b3 | ||
|
|
1b4ac9da8b | ||
|
|
d98310fc0e | ||
|
|
3240fca63e | ||
|
|
f1631b7f06 | ||
|
|
30e5c5f91b | ||
|
|
257026144d | ||
|
|
9f786dce97 | ||
|
|
c2f582164c | ||
|
|
464ed3b614 | ||
|
|
5bb9494ecc | ||
|
|
0fb583a094 | ||
|
|
358b1a7dbe | ||
|
|
bd91f439c8 | ||
|
|
4181ada887 | ||
|
|
32d116d106 | ||
|
|
30c27f9faf | ||
|
|
b332d576ab | ||
|
|
9def43cef0 | ||
|
|
0820b39a35 | ||
|
|
2a0be85d14 | ||
|
|
efb7262113 | ||
|
|
1a732bbb93 | ||
|
|
b8fe380b61 | ||
|
|
8670cea7a3 | ||
|
|
e2a5ec3616 | ||
|
|
d013366c9a | ||
|
|
e9093cda6d | ||
|
|
0f30a0ef3d | ||
|
|
b1a64e346c | ||
|
|
c524a89c5e | ||
|
|
e73d90e697 | ||
|
|
ee470d9ce9 | ||
|
|
aab5b3aaab | ||
|
|
86281b5fdb | ||
|
|
ddabf7db49 | ||
|
|
1c7523e98e | ||
|
|
120d084b12 | ||
|
|
1e69ec4634 | ||
|
|
31a680ce1c | ||
|
|
3bad19530e | ||
|
|
10986289e6 | ||
|
|
656c1b8d5d | ||
|
|
ef0037aa25 | ||
|
|
af02ccbd6f | ||
|
|
978f3f63bd | ||
|
|
e550cc0f43 | ||
|
|
5894226e93 | ||
|
|
d50fa8eeb7 | ||
|
|
6efd333684 | ||
|
|
05701b60c1 | ||
|
|
f8e7e55a00 | ||
|
|
20663f0226 | ||
|
|
ad175ba2ac | ||
|
|
bdf90a5e51 | ||
|
|
49618534ce | ||
|
|
f2bb2a6bee | ||
|
|
ba4f3aea7b | ||
|
|
b30068103b | ||
|
|
7062928c32 | ||
|
|
7f0764b7b1 | ||
|
|
8b21f4f869 | ||
|
|
8d634b9b1b | ||
|
|
698e567c63 | ||
|
|
6d697c3dda | ||
|
|
746e28c3a2 | ||
|
|
df0f087505 | ||
|
|
0ccec4c8c1 | ||
|
|
e18e1533e3 | ||
|
|
c077381e45 | ||
|
|
a0ecb78086 | ||
|
|
e47bd9faa4 | ||
|
|
e2bf6117dd | ||
|
|
14b0b332c5 | ||
|
|
76f74dabbe | ||
|
|
42dec2de39 | ||
|
|
b965971c79 | ||
|
|
3a7ab02f88 | ||
|
|
b931e935b5 | ||
|
|
521a1b7d34 | ||
|
|
fffcef2d30 | ||
|
|
cf1216a667 | ||
|
|
68ee647ed2 | ||
|
|
2eda952cd0 | ||
|
|
7fac4ac298 | ||
|
|
9016a5109d | ||
|
|
8e055fe587 | ||
|
|
3b2bb0590f | ||
|
|
134d3e2d0d | ||
|
|
b735f8e567 | ||
|
|
3992ea6656 | ||
|
|
03840990be | ||
|
|
27bafb1552 | ||
|
|
9b3ab17902 | ||
|
|
df0ede4ccc | ||
|
|
ecf6846255 | ||
|
|
173e22dde2 | ||
|
|
c5799c561a | ||
|
|
6736ca8fd4 | ||
|
|
8f3cacd32f | ||
|
|
d3cb3a1486 | ||
|
|
ae9dfca3b3 | ||
|
|
edc7c38ba0 | ||
|
|
54e76cf559 | ||
|
|
477cc8ba74 | ||
|
|
573d4c8151 | ||
|
|
5bdaec6980 | ||
|
|
400ff1ff6a | ||
|
|
1841cde776 | ||
|
|
990e696b37 | ||
|
|
d591c67276 | ||
|
|
423cd154a7 | ||
|
|
44dec3ab3f | ||
|
|
7fb7c9146b | ||
|
|
f060ba2094 | ||
|
|
457828260b | ||
|
|
4b080d4d0b | ||
|
|
5d83807357 | ||
|
|
2b794becff | ||
|
|
e69c5a0138 | ||
|
|
90a11c2ffc | ||
|
|
497da6487d | ||
|
|
8ffabf3db3 | ||
|
|
bf42605f88 | ||
|
|
7e12f17c48 | ||
|
|
9360a588ea | ||
|
|
e02e597102 | ||
|
|
a952a2e1e7 | ||
|
|
cb8668ffb8 | ||
|
|
79fb392a9a | ||
|
|
7b490ae26a | ||
|
|
69b05f932f | ||
|
|
e0d614fe2f | ||
|
|
5e81c3fdef | ||
|
|
4707b60ee4 | ||
|
|
158b1a87b3 | ||
|
|
a72f833c67 | ||
|
|
a9d0092bd2 | ||
|
|
154655c35c | ||
|
|
2a2f9c27a4 | ||
|
|
d50b8a7723 | ||
|
|
63421f7ed4 | ||
|
|
8ad24e2f9f | ||
|
|
941539ce23 | ||
|
|
74c4a80e3b | ||
|
|
6e30b31e9e | ||
|
|
b63161c73e | ||
|
|
9c362dced2 | ||
|
|
9a02c79e0a | ||
|
|
0ae4b6ff18 | ||
|
|
7b4166f28d | ||
|
|
bd87673db3 | ||
|
|
4cb3eabd4c | ||
|
|
d3957b5604 | ||
|
|
de072bc5dd | ||
|
|
7bb23efc2f | ||
|
|
88be284117 | ||
|
|
bc983e9f5d | ||
|
|
4c38de75ab | ||
|
|
b58469ce40 | ||
|
|
ab7f12058f | ||
|
|
0dda5a93c9 | ||
|
|
30092cc326 | ||
|
|
721380b153 | ||
|
|
09a0f21506 | ||
|
|
c9f2fdc847 | ||
|
|
e326cc94d0 | ||
|
|
66237dab24 | ||
|
|
53ec07a7f1 | ||
|
|
bbad80ae0e | ||
|
|
e6021a4f11 | ||
|
|
b3f792a2f3 | ||
|
|
7083a397b8 | ||
|
|
f98fd85fe9 | ||
|
|
f9f6e207d4 | ||
|
|
0c4e4e709f | ||
|
|
d7f9ad4916 | ||
|
|
b04f92ca3c | ||
|
|
16a0174cf1 | ||
|
|
c92d78e088 | ||
|
|
1f7b8d2416 | ||
|
|
7ca9b23aa3 | ||
|
|
f0acd8ddfd | ||
|
|
c5009dad31 | ||
|
|
9682d1d5ef | ||
|
|
a4e8fca784 | ||
|
|
8f25040bf5 | ||
|
|
34beec8d6b | ||
|
|
6c0fd638a5 | ||
|
|
0b94213af7 | ||
|
|
f874598fd8 | ||
|
|
a1adcd3a5a | ||
|
|
1596b98e25 | ||
|
|
9b0ad5c545 | ||
|
|
6a47b30987 | ||
|
|
79594a9d00 | ||
|
|
38a9818482 | ||
|
|
a407d538f5 | ||
|
|
44bea85296 | ||
|
|
915d26adfa | ||
|
|
3dd4248587 | ||
|
|
7969e58fbf | ||
|
|
7043ebda23 | ||
|
|
4c0a5b7553 | ||
|
|
533fbe0c2f | ||
|
|
437dfd5f02 | ||
|
|
5f4962ddcc | ||
|
|
7efa609a13 | ||
|
|
0d7049ea7c | ||
|
|
997e7f0420 | ||
|
|
96619b9565 | ||
|
|
4c2a786e54 | ||
|
|
469b1571e1 | ||
|
|
3bc66e0d27 | ||
|
|
9a4fac600a | ||
|
|
546ba8b68f | ||
|
|
ed29c0633f | ||
|
|
35b1135b50 | ||
|
|
90403c98c9 | ||
|
|
71a1c0574a | ||
|
|
ba64a50bb5 | ||
|
|
05131b2b76 | ||
|
|
0894eaee28 | ||
|
|
6f2fd4eccc | ||
|
|
04b534bda1 | ||
|
|
3620796d6d | ||
|
|
a321a38ccd | ||
|
|
ea965dfa85 | ||
|
|
f381106de2 | ||
|
|
b9ab3d6490 | ||
|
|
4cf1d1e08b | ||
|
|
cba6e4df64 | ||
|
|
0dd6f38748 | ||
|
|
970ba437a0 | ||
|
|
e0bbbe3894 | ||
|
|
504791b5b6 | ||
|
|
6a6d0b48b9 | ||
|
|
84ff83bbe2 | ||
|
|
787bcc3546 | ||
|
|
fd811d8cf4 | ||
|
|
3fa743f64b | ||
|
|
ec374c050a | ||
|
|
5a07f8a2a3 | ||
|
|
91b09dc43f | ||
|
|
8d6d355a3b | ||
|
|
da6fd69398 | ||
|
|
0e623cfd15 | ||
|
|
1c01d8f59f | ||
|
|
5723ee7b19 | ||
|
|
1d85292451 |
@@ -122,9 +122,8 @@ dotnet_code_quality.ca3012.excluded_symbol_names = BotController|CommandControll
|
||||
|
||||
dotnet_code_quality_unused_parameters = all:warning
|
||||
|
||||
dotnet_diagnostic.ca1028.severity = silent
|
||||
dotnet_diagnostic.ca1031.severity = silent
|
||||
dotnet_diagnostic.ca1863.severity = silent
|
||||
dotnet_diagnostic.CA1028.severity = silent
|
||||
dotnet_diagnostic.CA1031.severity = silent
|
||||
|
||||
# Rule - almost everything
|
||||
dotnet_naming_rule.almost_everything_must_be_pascal_case.severity = warning
|
||||
@@ -226,6 +225,10 @@ dotnet_style_qualification_for_property = false:warning
|
||||
dotnet_style_readonly_field = true:warning
|
||||
dotnet_style_require_accessibility_modifiers = always:warning
|
||||
|
||||
[ArchiSteamFarm/**.cs]
|
||||
# ASF project includes plugin system, therefore CA1515 typically doesn't make sense there
|
||||
dotnet_diagnostic.CA1515.severity = silent
|
||||
|
||||
###############################
|
||||
# JetBrains, IntelliJ/Rider #
|
||||
###############################
|
||||
|
||||
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -1,7 +1,11 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Unix files that are always LF
|
||||
*.sh text eol=lf
|
||||
|
||||
# Custom for Visual Studio
|
||||
# Windows files that are always CRLF
|
||||
[Dd]esktop.ini text eol=crlf
|
||||
|
||||
# Diff settings
|
||||
*.cs diff=csharp
|
||||
|
||||
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@@ -1,4 +1,2 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: JustArchi
|
||||
custom: ["https://paypal.me/JustArchi", "https://pay.revolut.com/justarchi", "https://commerce.coinbase.com/checkout/0c23b844-c51b-45f4-9135-8db7c6fcf98e", "https://steamcommunity.com/tradeoffer/new/?partner=46697991&token=0ix2Ruv_"]
|
||||
custom: ["https://paypal.me/JustArchi", "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HD2P2P3WGS5Y4", "https://pay.revolut.com/justarchi", "https://steamcommunity.com/tradeoffer/new/?partner=46697991&token=0ix2Ruv_"]
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -7,8 +7,8 @@ contact_links:
|
||||
url: https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Localization
|
||||
about: Please use our crowdin platform
|
||||
- name: ❓ Support question or technical issue
|
||||
url: https://github.com/JustArchiNET/ArchiSteamFarm/blob/main/.github/SUPPORT.md
|
||||
about: Please review our support guidelines
|
||||
url: https://github.com/JustArchiNET/ArchiSteamFarm/discussions/categories/support-english
|
||||
about: Please use GitHub discussions or other support channels
|
||||
- name: 🗯️ Negative feedback, complaints and demands
|
||||
url: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
||||
about: We're taking those very seriously
|
||||
|
||||
6
.github/RELEASE_TEMPLATE.md
vendored
6
.github/RELEASE_TEMPLATE.md
vendored
@@ -1,6 +1,6 @@
|
||||
### Notice
|
||||
|
||||
**Pre-releases are experimental versions that often contain unpatched bugs, work-in-progress features and rewritten implementations. If you don't consider yourself advanced user, please download **[latest stable release](https://github.com/JustArchiNET/ArchiSteamFarm/releases/latest)** instead. Pre-release versions are dedicated to users who know how to report bugs, deal with issues and give feedback - no technical support will be given. Check out ASF **[release cycle](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Release-cycle)** if you'd like to learn more.**
|
||||
**Pre-releases are test versions that often contain unpatched bugs, work-in-progress features and rewritten implementations. If you don't consider yourself advanced user, please download **[latest stable release](https://github.com/JustArchiNET/ArchiSteamFarm/releases/latest)** instead. Pre-release versions are dedicated to users who know how to report bugs, deal with issues and give feedback - no technical support will be given. Check out ASF **[release cycle](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Release-cycle)** if you'd like to learn more.**
|
||||
|
||||
---
|
||||
|
||||
@@ -14,4 +14,6 @@ This is automated GitHub deployment, human-readable changelog should be availabl
|
||||
|
||||
ASF is available for free, this release was made possible thanks to the people that decided to support the project. If you're grateful for what we're doing, please consider a donation. Developing ASF requires massive amount of time and knowledge, especially when it comes to Steam (and its problems). Even $1 is highly appreciated and shows that you care. Thank you!
|
||||
|
||||
[](https://github.com/sponsors/JustArchi) [](https://commerce.coinbase.com/checkout/0c23b844-c51b-45f4-9135-8db7c6fcf98e) [](https://paypal.me/JustArchi) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HD2P2P3WGS5Y4) [](https://pay.revolut.com/justarchi) [](https://steamcommunity.com/tradeoffer/new/?partner=46697991&token=0ix2Ruv_)
|
||||
[](https://github.com/sponsors/JustArchi) [](https://paypal.me/JustArchi) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HD2P2P3WGS5Y4) [](https://pay.revolut.com/justarchi) [](https://steamcommunity.com/tradeoffer/new/?partner=46697991&token=0ix2Ruv_)
|
||||
|
||||
[](https://www.blockchain.com/explorer/addresses/btc/3HwcgZbtoF5vSxJkNUvThVSJipKi7r5EqU) [](https://www.blockchain.com/explorer/addresses/eth/0xA1F7Ba62C5a3A8b93Fe6656936192432F328a366) [](https://live.blockcypher.com/ltc/address/MJCeBEZUsNgDhRhqbLFfPiDcf7CSrdvmZ3) [](https://etherscan.io/address/0xCf42D9F53F974CBd7c304eF0243CAe8e029885A8) [](https://etherscan.io/address/0x985FDdD3AD00838A2049B07A33b783104d60f776)
|
||||
|
||||
0
qodana.yaml → .github/qodana.yaml
vendored
0
qodana.yaml → .github/qodana.yaml
vendored
10
.github/renovate.json5
vendored
10
.github/renovate.json5
vendored
@@ -12,13 +12,5 @@
|
||||
],
|
||||
"git-submodules": {
|
||||
"enabled": true
|
||||
},
|
||||
"packageRules": [
|
||||
{
|
||||
// TODO: <= 3.1 for Mono support, last failed version 6.12, https://steamcommunity.com/groups/archiasf/discussions/1/2997673517556002529
|
||||
"allowedVersions": "<= 3.1",
|
||||
"matchManagers": [ "nuget" ],
|
||||
"matchPackageNames": [ "Microsoft.Extensions.Configuration.Json", "Microsoft.Extensions.Logging.Configuration" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
@@ -5,7 +5,7 @@ on: [push, pull_request]
|
||||
env:
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
||||
DOTNET_NOLOGO: true
|
||||
DOTNET_SDK_VERSION: 8.0
|
||||
DOTNET_SDK_VERSION: 9.0
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -21,13 +21,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4.1.1
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4.0.0
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
|
||||
|
||||
@@ -39,12 +39,3 @@ jobs:
|
||||
|
||||
- name: Run ${{ matrix.configuration }} ArchiSteamFarm.Tests
|
||||
run: dotnet test ArchiSteamFarm.Tests -c "${{ matrix.configuration }}" -p:ContinuousIntegrationBuild=true -p:UseAppHost=false --nologo
|
||||
|
||||
- name: Upload latest strings for translation on Crowdin
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.configuration == 'Release' && startsWith(matrix.os, 'ubuntu-') }}
|
||||
uses: crowdin/github-action@v1.19.0
|
||||
with:
|
||||
crowdin_branch_name: main
|
||||
config: '.github/crowdin.yml'
|
||||
project_id: ${{ secrets.ASF_CROWDIN_PROJECT_ID }}
|
||||
token: ${{ secrets.ASF_CROWDIN_API_TOKEN }}
|
||||
|
||||
24
.github/workflows/code-quality.yml
vendored
24
.github/workflows/code-quality.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: ASF-code-quality
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
- push
|
||||
|
||||
env:
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
||||
@@ -14,32 +15,25 @@ permissions:
|
||||
|
||||
jobs:
|
||||
main:
|
||||
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
environment: qa-qodana
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: actions/checkout@v4.1.1
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
|
||||
- name: Checkout code (for PR)
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/checkout@v4.1.1
|
||||
with:
|
||||
fetch-depth: 100 # History is required for pull request analysis
|
||||
ref: ${{ github.event.pull_request.head.sha }} # To check out the actual pull request commit, not the merge commit
|
||||
show-progress: false
|
||||
|
||||
- name: Run Qodana scan
|
||||
uses: JetBrains/qodana-action@v2023.3.1
|
||||
uses: JetBrains/qodana-action@v2024.2.6
|
||||
with:
|
||||
args: --property=idea.headless.enable.statistics=false
|
||||
args: --config,.github/qodana.yaml,--property=idea.headless.enable.statistics=false
|
||||
pr-mode: false
|
||||
upload-result: true
|
||||
env:
|
||||
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
|
||||
|
||||
- name: Report Qodana results to GitHub
|
||||
uses: github/codeql-action/upload-sarif@v3.24.7
|
||||
uses: github/codeql-action/upload-sarif@v3.27.4
|
||||
with:
|
||||
sarif_file: ${{ runner.temp }}/qodana/results/qodana.sarif.json
|
||||
|
||||
28
.github/workflows/crowdin-ci.yml
vendored
Normal file
28
.github/workflows/crowdin-ci.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: ASF-crowdin-ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
upload:
|
||||
environment: dev-crowdin
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
submodules: recursive
|
||||
|
||||
- name: Upload latest strings for translation on Crowdin
|
||||
uses: crowdin/github-action@v2.3.0
|
||||
with:
|
||||
crowdin_branch_name: main
|
||||
config: '.github/crowdin.yml'
|
||||
project_id: ${{ secrets.ASF_CROWDIN_PROJECT_ID }}
|
||||
token: ${{ secrets.ASF_CROWDIN_API_TOKEN }}
|
||||
12
.github/workflows/docker-ci.yml
vendored
12
.github/workflows/docker-ci.yml
vendored
@@ -19,20 +19,20 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4.1.1
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3.2.0
|
||||
uses: docker/setup-buildx-action@v3.7.1
|
||||
|
||||
- name: Build ${{ matrix.configuration }} Docker image from ${{ matrix.file }}
|
||||
uses: docker/build-push-action@v5.3.0
|
||||
uses: docker/build-push-action@v6.9.0
|
||||
with:
|
||||
build-args: CONFIGURATION=${{ matrix.configuration }}
|
||||
context: .
|
||||
file: ${{ matrix.file }}
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
build-args: |
|
||||
CONFIGURATION=${{ matrix.configuration }}
|
||||
STEAM_TOKEN_DUMPER_TOKEN=${{ secrets.STEAM_TOKEN_DUMPER_TOKEN }}
|
||||
provenance: true
|
||||
sbom: true
|
||||
|
||||
27
.github/workflows/docker-publish-latest.yml
vendored
27
.github/workflows/docker-publish-latest.yml
vendored
@@ -5,7 +5,6 @@ on:
|
||||
types: [released]
|
||||
|
||||
env:
|
||||
ASF_PRIVATE_SNK: ${{ secrets.ASF_PRIVATE_SNK }}
|
||||
PLATFORMS: linux/amd64,linux/arm,linux/arm64
|
||||
TAG: latest
|
||||
|
||||
@@ -14,40 +13,32 @@ permissions:
|
||||
|
||||
jobs:
|
||||
main:
|
||||
environment: release-docker
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4.1.1
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3.2.0
|
||||
uses: docker/setup-buildx-action@v3.7.1
|
||||
|
||||
- name: Login to ghcr.io
|
||||
uses: docker/login-action@v3.1.0
|
||||
uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3.1.0
|
||||
uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Prepare private key for signing
|
||||
shell: sh
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
if [ -n "${ASF_PRIVATE_SNK-}" ]; then
|
||||
echo "$ASF_PRIVATE_SNK" | base64 -d > "resources/ArchiSteamFarm.snk"
|
||||
fi
|
||||
|
||||
- name: Prepare environment outputs
|
||||
shell: sh
|
||||
run: |
|
||||
@@ -59,12 +50,16 @@ jobs:
|
||||
echo "DH_REPOSITORY=$(echo ${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }} | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build and publish Docker image from Dockerfile.Service
|
||||
uses: docker/build-push-action@v5.3.0
|
||||
uses: docker/build-push-action@v6.9.0
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile.Service
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
build-args: STEAM_TOKEN_DUMPER_TOKEN=${{ secrets.STEAM_TOKEN_DUMPER_TOKEN }}
|
||||
provenance: true
|
||||
sbom: true
|
||||
secrets: |
|
||||
ASF_PRIVATE_SNK=${{ secrets.ASF_PRIVATE_SNK }}
|
||||
STEAM_TOKEN_DUMPER_TOKEN=${{ secrets.STEAM_TOKEN_DUMPER_TOKEN }}
|
||||
labels: |
|
||||
org.opencontainers.image.created=${{ env.DATE_ISO8601 }}
|
||||
org.opencontainers.image.version=${{ env.FIXED_TAG }}
|
||||
|
||||
29
.github/workflows/docker-publish-main.yml
vendored
29
.github/workflows/docker-publish-main.yml
vendored
@@ -6,7 +6,6 @@ on:
|
||||
- main
|
||||
|
||||
env:
|
||||
ASF_PRIVATE_SNK: ${{ secrets.ASF_PRIVATE_SNK }}
|
||||
PLATFORMS: linux/amd64,linux/arm,linux/arm64
|
||||
TAG: main
|
||||
|
||||
@@ -15,40 +14,32 @@ permissions:
|
||||
|
||||
jobs:
|
||||
main:
|
||||
environment: release-docker
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4.1.1
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3.2.0
|
||||
uses: docker/setup-buildx-action@v3.7.1
|
||||
|
||||
- name: Login to ghcr.io
|
||||
uses: docker/login-action@v3.1.0
|
||||
uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3.1.0
|
||||
uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Prepare private key for signing
|
||||
shell: sh
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
if [ -n "${ASF_PRIVATE_SNK-}" ]; then
|
||||
echo "$ASF_PRIVATE_SNK" | base64 -d > "resources/ArchiSteamFarm.snk"
|
||||
fi
|
||||
|
||||
- name: Prepare environment outputs
|
||||
shell: sh
|
||||
run: |
|
||||
@@ -59,11 +50,15 @@ jobs:
|
||||
echo "DH_REPOSITORY=$(echo ${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }} | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build and publish Docker image from Dockerfile
|
||||
uses: docker/build-push-action@v5.3.0
|
||||
uses: docker/build-push-action@v6.9.0
|
||||
with:
|
||||
context: .
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
build-args: STEAM_TOKEN_DUMPER_TOKEN=${{ secrets.STEAM_TOKEN_DUMPER_TOKEN }}
|
||||
provenance: true
|
||||
sbom: true
|
||||
secrets: |
|
||||
ASF_PRIVATE_SNK=${{ secrets.ASF_PRIVATE_SNK }}
|
||||
STEAM_TOKEN_DUMPER_TOKEN=${{ secrets.STEAM_TOKEN_DUMPER_TOKEN }}
|
||||
labels: |
|
||||
org.opencontainers.image.created=${{ env.DATE_ISO8601 }}
|
||||
org.opencontainers.image.version=${{ github.sha }}
|
||||
@@ -77,6 +72,6 @@ jobs:
|
||||
uses: peter-evans/dockerhub-description@v4.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
repository: ${{ env.DH_REPOSITORY }}
|
||||
short-description: ${{ github.event.repository.description }}
|
||||
|
||||
27
.github/workflows/docker-publish-released.yml
vendored
27
.github/workflows/docker-publish-released.yml
vendored
@@ -6,7 +6,6 @@ on:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
ASF_PRIVATE_SNK: ${{ secrets.ASF_PRIVATE_SNK }}
|
||||
PLATFORMS: linux/amd64,linux/arm,linux/arm64
|
||||
TAG: released
|
||||
|
||||
@@ -15,40 +14,32 @@ permissions:
|
||||
|
||||
jobs:
|
||||
main:
|
||||
environment: release-docker
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4.1.1
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3.2.0
|
||||
uses: docker/setup-buildx-action@v3.7.1
|
||||
|
||||
- name: Login to ghcr.io
|
||||
uses: docker/login-action@v3.1.0
|
||||
uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3.1.0
|
||||
uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Prepare private key for signing
|
||||
shell: sh
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
if [ -n "${ASF_PRIVATE_SNK-}" ]; then
|
||||
echo "$ASF_PRIVATE_SNK" | base64 -d > "resources/ArchiSteamFarm.snk"
|
||||
fi
|
||||
|
||||
- name: Prepare environment outputs
|
||||
shell: sh
|
||||
run: |
|
||||
@@ -60,11 +51,15 @@ jobs:
|
||||
echo "DH_REPOSITORY=$(echo ${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }} | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build and publish Docker image from Dockerfile
|
||||
uses: docker/build-push-action@v5.3.0
|
||||
uses: docker/build-push-action@v6.9.0
|
||||
with:
|
||||
context: .
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
build-args: STEAM_TOKEN_DUMPER_TOKEN=${{ secrets.STEAM_TOKEN_DUMPER_TOKEN }}
|
||||
provenance: true
|
||||
sbom: true
|
||||
secrets: |
|
||||
ASF_PRIVATE_SNK=${{ secrets.ASF_PRIVATE_SNK }}
|
||||
STEAM_TOKEN_DUMPER_TOKEN=${{ secrets.STEAM_TOKEN_DUMPER_TOKEN }}
|
||||
labels: |
|
||||
org.opencontainers.image.created=${{ env.DATE_ISO8601 }}
|
||||
org.opencontainers.image.version=${{ env.FIXED_TAG }}
|
||||
|
||||
400
.github/workflows/publish.yml
vendored
400
.github/workflows/publish.yml
vendored
@@ -6,9 +6,10 @@ env:
|
||||
CONFIGURATION: Release
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
||||
DOTNET_NOLOGO: true
|
||||
DOTNET_SDK_VERSION: 8.0
|
||||
DOTNET_SDK_VERSION: 9.0
|
||||
NODE_JS_VERSION: 'lts/*'
|
||||
PLUGINS: ArchiSteamFarm.OfficialPlugins.ItemsMatcher ArchiSteamFarm.OfficialPlugins.MobileAuthenticator ArchiSteamFarm.OfficialPlugins.SteamTokenDumper
|
||||
PLUGINS_BUNDLED: ArchiSteamFarm.OfficialPlugins.ItemsMatcher ArchiSteamFarm.OfficialPlugins.MobileAuthenticator ArchiSteamFarm.OfficialPlugins.SteamTokenDumper
|
||||
PLUGINS_INCLUDED: ArchiSteamFarm.OfficialPlugins.Monitoring # Apart from declaring them here, there is certain amount of hardcoding needed below for uploading
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -18,13 +19,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4.1.1
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup Node.js with npm
|
||||
uses: actions/setup-node@v4.0.2
|
||||
uses: actions/setup-node@v4.1.0
|
||||
with:
|
||||
check-latest: true
|
||||
node-version: ${{ env.NODE_JS_VERSION }}
|
||||
@@ -42,8 +43,9 @@ jobs:
|
||||
run: npm run-script deploy --no-progress --prefix ASF-ui
|
||||
|
||||
- name: Upload ASF-ui
|
||||
uses: actions/upload-artifact@v4.3.1
|
||||
uses: actions/upload-artifact@v4.4.3
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ASF-ui
|
||||
path: ASF-ui/dist
|
||||
|
||||
@@ -71,16 +73,21 @@ jobs:
|
||||
- os: windows-latest
|
||||
variant: win-x64
|
||||
|
||||
environment: build
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
permissions:
|
||||
attestations: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4.1.1
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4.0.0
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
|
||||
|
||||
@@ -88,7 +95,7 @@ jobs:
|
||||
run: dotnet --info
|
||||
|
||||
- name: Download previously built ASF-ui
|
||||
uses: actions/download-artifact@v4.1.4
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: ASF-ui
|
||||
path: ASF-ui/dist
|
||||
@@ -125,35 +132,6 @@ jobs:
|
||||
}
|
||||
}
|
||||
|
||||
- name: Prepare for publishing on Unix
|
||||
if: startsWith(matrix.os, 'macos-') || startsWith(matrix.os, 'ubuntu-')
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
dotnet restore
|
||||
dotnet build ArchiSteamFarm -c "$CONFIGURATION" -p:ContinuousIntegrationBuild=true -p:TargetLatestRuntimePatch=false -p:UseAppHost=false --nologo
|
||||
|
||||
- name: Prepare for publishing on Windows
|
||||
if: startsWith(matrix.os, 'windows-')
|
||||
shell: pwsh
|
||||
run: |
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
dotnet restore
|
||||
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Last command failed."
|
||||
}
|
||||
|
||||
dotnet build ArchiSteamFarm -c "$env:CONFIGURATION" -p:ContinuousIntegrationBuild=true -p:TargetLatestRuntimePatch=false -p:UseAppHost=false --nologo
|
||||
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Last command failed."
|
||||
}
|
||||
|
||||
- name: Prepare ArchiSteamFarm.OfficialPlugins.SteamTokenDumper on Unix
|
||||
if: startsWith(matrix.os, 'macos-') || startsWith(matrix.os, 'ubuntu-')
|
||||
env:
|
||||
@@ -181,69 +159,6 @@ jobs:
|
||||
(Get-Content "ArchiSteamFarm.OfficialPlugins.SteamTokenDumper\SharedInfo.cs").Replace('STEAM_TOKEN_DUMPER_TOKEN', "$env:STEAM_TOKEN_DUMPER_TOKEN") | Set-Content "ArchiSteamFarm.OfficialPlugins.SteamTokenDumper\SharedInfo.cs"
|
||||
}
|
||||
|
||||
- name: Publish official plugins on Unix
|
||||
if: startsWith(matrix.os, 'macos-') || startsWith(matrix.os, 'ubuntu-')
|
||||
env:
|
||||
MAX_JOBS: 4
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
publish() {
|
||||
dotnet publish "$1" -c "$CONFIGURATION" -o "out/${1}" -p:ContinuousIntegrationBuild=true -p:TargetLatestRuntimePatch=false -p:UseAppHost=false --no-restore --nologo
|
||||
}
|
||||
|
||||
for plugin in $PLUGINS; do
|
||||
while [ "$(jobs -p | wc -l)" -ge "$MAX_JOBS" ]; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
publish "$plugin" &
|
||||
done
|
||||
|
||||
wait
|
||||
|
||||
- name: Publish official plugins on Windows
|
||||
if: startsWith(matrix.os, 'windows-')
|
||||
env:
|
||||
MAX_JOBS: 4
|
||||
shell: pwsh
|
||||
run: |
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
$PublishBlock = {
|
||||
param($plugin)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
Set-Location "$env:GITHUB_WORKSPACE"
|
||||
|
||||
dotnet publish "$plugin" -c "$env:CONFIGURATION" -o "out\$plugin" -p:ContinuousIntegrationBuild=true -p:TargetLatestRuntimePatch=false -p:UseAppHost=false --no-restore --nologo
|
||||
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Last command failed."
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($plugin in $env:PLUGINS.Split([char[]] $null, [System.StringSplitOptions]::RemoveEmptyEntries)) {
|
||||
# Limit active jobs in parallel to help with memory usage
|
||||
$jobs = $(Get-Job -State Running)
|
||||
|
||||
while (@($jobs).Count -ge $env:MAX_JOBS) {
|
||||
Wait-Job -Job $jobs -Any | Out-Null
|
||||
|
||||
$jobs = $(Get-Job -State Running)
|
||||
}
|
||||
|
||||
Start-Job -Name "$plugin" $PublishBlock -ArgumentList "$plugin"
|
||||
}
|
||||
|
||||
Get-Job | Receive-Job -Wait
|
||||
|
||||
- name: Publish ASF-${{ matrix.variant }} on Unix
|
||||
if: startsWith(matrix.os, 'macos-') || startsWith(matrix.os, 'ubuntu-')
|
||||
env:
|
||||
@@ -260,28 +175,12 @@ jobs:
|
||||
|
||||
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -o "out/${VARIANT}" "-p:ASFVariant=${VARIANT}" -p:ContinuousIntegrationBuild=true --nologo $variantArgs
|
||||
|
||||
# If we're including official plugins for this framework, copy them to output directory
|
||||
for plugin in $PLUGINS; do
|
||||
if [ -d "out/${plugin}" ]; then
|
||||
mkdir -p "out/${VARIANT}/plugins/${plugin}"
|
||||
cp -pR "out/${plugin}/"* "out/${VARIANT}/plugins/${plugin}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Include .ico file for all platforms, since only Windows script can bundle it inside the exe
|
||||
cp "resources/ASF.ico" "out/${VARIANT}/ArchiSteamFarm.ico"
|
||||
|
||||
# By default use fastest compression
|
||||
seven_zip_args="-mx=1"
|
||||
zip_args="-1"
|
||||
|
||||
# Include extra logic for builds marked for release
|
||||
case "$GITHUB_REF" in
|
||||
"refs/tags/"*)
|
||||
# Tweak compression args for release publishing
|
||||
seven_zip_args="-mx=9 -mfb=258 -mpass=15"
|
||||
zip_args="-9"
|
||||
|
||||
# Update link in Changelog.html accordingly
|
||||
if [ -f "out/${VARIANT}/Changelog.html" ]; then
|
||||
tag="$(echo "$GITHUB_REF" | cut -c 11-)"
|
||||
@@ -292,37 +191,6 @@ jobs:
|
||||
;;
|
||||
esac
|
||||
|
||||
# Create the final zip file
|
||||
case "$(uname -s)" in
|
||||
"Darwin")
|
||||
# We prefer to use zip on macOS as 7z implementation on that OS doesn't handle file permissions (chmod +x)
|
||||
if command -v zip >/dev/null; then
|
||||
(
|
||||
cd "${GITHUB_WORKSPACE}/out/${VARIANT}"
|
||||
zip -q -r $zip_args "../ASF-${VARIANT}.zip" .
|
||||
)
|
||||
elif command -v 7z >/dev/null; then
|
||||
7z a -bd -slp -tzip -mm=Deflate $seven_zip_args "out/ASF-${VARIANT}.zip" "${GITHUB_WORKSPACE}/out/${VARIANT}/*"
|
||||
else
|
||||
echo "ERROR: No supported zip tool!"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if command -v 7z >/dev/null; then
|
||||
7z a -bd -slp -tzip -mm=Deflate $seven_zip_args "out/ASF-${VARIANT}.zip" "${GITHUB_WORKSPACE}/out/${VARIANT}/*"
|
||||
elif command -v zip >/dev/null; then
|
||||
(
|
||||
cd "${GITHUB_WORKSPACE}/out/${VARIANT}"
|
||||
zip -q -r $zip_args "../ASF-${VARIANT}.zip" .
|
||||
)
|
||||
else
|
||||
echo "ERROR: No supported zip tool!"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: Publish ASF-${{ matrix.variant }} on Windows
|
||||
if: startsWith(matrix.os, 'windows-')
|
||||
env:
|
||||
@@ -345,30 +213,13 @@ jobs:
|
||||
throw "Last command failed."
|
||||
}
|
||||
|
||||
# If we're including official plugins for this framework, copy them to output directory
|
||||
foreach ($plugin in $env:PLUGINS.Split([char[]] $null, [System.StringSplitOptions]::RemoveEmptyEntries)) {
|
||||
if (Test-Path "out\$plugin" -PathType Container) {
|
||||
if (!(Test-Path "out\$env:VARIANT\plugins\$plugin" -PathType Container)) {
|
||||
New-Item -ItemType Directory -Path "out\$env:VARIANT\plugins\$plugin" > $null
|
||||
}
|
||||
|
||||
Copy-Item "out\$plugin\*" "out\$env:VARIANT\plugins\$plugin" -Recurse
|
||||
}
|
||||
}
|
||||
|
||||
# Icon is available only in .exe Windows builds, we'll bundle the .ico file for other flavours
|
||||
if (!(Test-Path "out\$env:VARIANT\ArchiSteamFarm.exe" -PathType Leaf)) {
|
||||
Copy-Item 'resources\ASF.ico' "out\$env:VARIANT\ArchiSteamFarm.ico"
|
||||
}
|
||||
|
||||
# By default use fastest compression
|
||||
$compressionArgs = '-mx=1'
|
||||
|
||||
# Include extra logic for builds marked for release
|
||||
if ($env:GITHUB_REF -like 'refs/tags/*') {
|
||||
# Tweak compression args for release publishing
|
||||
$compressionArgs = '-mx=9', '-mfb=258', '-mpass=15'
|
||||
|
||||
# Update link in Changelog.html accordingly
|
||||
if (Test-Path "out\$env:VARIANT\Changelog.html" -PathType Leaf) {
|
||||
$tag = $env:GITHUB_REF.Substring(10)
|
||||
@@ -377,6 +228,111 @@ jobs:
|
||||
}
|
||||
}
|
||||
|
||||
- name: Publish bundled plugins on Unix
|
||||
if: startsWith(matrix.os, 'macos-') || startsWith(matrix.os, 'ubuntu-')
|
||||
env:
|
||||
VARIANT: ${{ matrix.variant }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$VARIANT" = 'generic' ]; then
|
||||
variantArgs="-p:TargetLatestRuntimePatch=false -p:UseAppHost=false"
|
||||
else
|
||||
variantArgs="-r $VARIANT"
|
||||
fi
|
||||
|
||||
for plugin in $PLUGINS_BUNDLED; do
|
||||
dotnet publish "$plugin" -c "$CONFIGURATION" -o "out/${VARIANT}/plugins/${plugin}" "-p:ASFVariant=${VARIANT}" -p:ContinuousIntegrationBuild=true --nologo $variantArgs
|
||||
done
|
||||
|
||||
- name: Publish bundled plugins on Windows
|
||||
if: startsWith(matrix.os, 'windows-')
|
||||
env:
|
||||
VARIANT: ${{ matrix.variant }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
if ($env:VARIANT -like 'generic*') {
|
||||
$variantArgs = '-p:TargetLatestRuntimePatch=false', '-p:UseAppHost=false'
|
||||
} else {
|
||||
$variantArgs = '-r', "$env:VARIANT"
|
||||
}
|
||||
|
||||
foreach ($plugin in $env:PLUGINS_BUNDLED.Split([char[]] $null, [System.StringSplitOptions]::RemoveEmptyEntries)) {
|
||||
dotnet publish "$plugin" -c "$env:CONFIGURATION" -o "out\$env:VARIANT\plugins\$plugin" "-p:ASFVariant=$env:VARIANT" -p:ContinuousIntegrationBuild=true --nologo $variantArgs
|
||||
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Last command failed."
|
||||
}
|
||||
}
|
||||
|
||||
- name: Zip ASF-${{ matrix.variant }} on Unix
|
||||
if: startsWith(matrix.os, 'macos-') || startsWith(matrix.os, 'ubuntu-')
|
||||
env:
|
||||
VARIANT: ${{ matrix.variant }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# By default use fastest compression
|
||||
seven_zip_args="-mx=1"
|
||||
zip_args="-1"
|
||||
|
||||
# Tweak compression args for release publishing
|
||||
case "$GITHUB_REF" in
|
||||
"refs/tags/"*)
|
||||
seven_zip_args="-mx=9 -mfb=258 -mpass=15"
|
||||
zip_args="-9"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Create the final zip file
|
||||
case "$(uname -s)" in
|
||||
"Darwin")
|
||||
# We prefer to use zip on macOS as 7z implementation on that OS doesn't handle file permissions (chmod +x)
|
||||
if command -v zip >/dev/null; then
|
||||
(
|
||||
cd "${GITHUB_WORKSPACE}/out/${VARIANT}"
|
||||
zip -q -r $zip_args "../ASF-${VARIANT}.zip" .
|
||||
)
|
||||
else
|
||||
7z a -bd -slp -tzip -mm=Deflate $seven_zip_args "out/ASF-${VARIANT}.zip" "${GITHUB_WORKSPACE}/out/${VARIANT}/*"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if command -v 7z >/dev/null; then
|
||||
7z a -bd -slp -tzip -mm=Deflate $seven_zip_args "out/ASF-${VARIANT}.zip" "${GITHUB_WORKSPACE}/out/${VARIANT}/*"
|
||||
else
|
||||
(
|
||||
cd "${GITHUB_WORKSPACE}/out/${VARIANT}"
|
||||
zip -q -r $zip_args "../ASF-${VARIANT}.zip" .
|
||||
)
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: Zip ASF-${{ matrix.variant }} on Windows
|
||||
if: startsWith(matrix.os, 'windows-')
|
||||
env:
|
||||
VARIANT: ${{ matrix.variant }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
# By default use fastest compression
|
||||
$compressionArgs = '-mx=1'
|
||||
|
||||
# Tweak compression args for release publishing
|
||||
if ($env:GITHUB_REF -like 'refs/tags/*') {
|
||||
$compressionArgs = '-mx=9', '-mfb=258', '-mpass=15'
|
||||
}
|
||||
|
||||
# Create the final zip file
|
||||
7z a -bd -slp -tzip -mm=Deflate $compressionArgs "out\ASF-$env:VARIANT.zip" "$env:GITHUB_WORKSPACE\out\$env:VARIANT\*"
|
||||
|
||||
@@ -404,109 +360,185 @@ jobs:
|
||||
}
|
||||
}
|
||||
|
||||
- name: Upload ASF-${{ matrix.variant }}
|
||||
uses: actions/upload-artifact@v4.3.1
|
||||
- name: Generate artifact attestation for ASF-${{ matrix.variant }}.zip
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
uses: actions/attest-build-provenance@v1.4.4
|
||||
with:
|
||||
subject-path: out/ASF-${{ matrix.variant }}.zip
|
||||
|
||||
- name: Upload ASF-${{ matrix.variant }}
|
||||
uses: actions/upload-artifact@v4.4.3
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ${{ matrix.os }}_ASF-${{ matrix.variant }}
|
||||
path: out/ASF-${{ matrix.variant }}.zip
|
||||
|
||||
- name: Publish included plugins on Unix
|
||||
if: ${{ matrix.os == 'ubuntu-latest' && matrix.variant == 'generic' }}
|
||||
env:
|
||||
VARIANT: ${{ matrix.variant }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# By default use fastest compression
|
||||
seven_zip_args="-mx=1"
|
||||
zip_args="-1"
|
||||
|
||||
# Tweak compression args for release publishing
|
||||
case "$GITHUB_REF" in
|
||||
"refs/tags/"*)
|
||||
seven_zip_args="-mx=9 -mfb=258 -mpass=15"
|
||||
zip_args="-9"
|
||||
;;
|
||||
esac
|
||||
|
||||
for plugin in $PLUGINS_INCLUDED; do
|
||||
dotnet publish "$plugin" -c "$CONFIGURATION" -o "out/${plugin}" "-p:ASFVariant=${VARIANT}" -p:ContinuousIntegrationBuild=true -p:TargetLatestRuntimePatch=false -p:UseAppHost=false --nologo
|
||||
|
||||
# Create the final zip file
|
||||
if command -v 7z >/dev/null; then
|
||||
7z a -bd -slp -tzip -mm=Deflate $seven_zip_args "out/${plugin}.zip" "${GITHUB_WORKSPACE}/out/${plugin}/*"
|
||||
else
|
||||
(
|
||||
cd "${GITHUB_WORKSPACE}/out/${plugin}"
|
||||
zip -q -r $zip_args "../${plugin}.zip" .
|
||||
)
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Generate artifact attestation for ArchiSteamFarm.OfficialPlugins.Monitoring
|
||||
if: ${{ github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.variant == 'generic' }}
|
||||
uses: actions/attest-build-provenance@v1.4.4
|
||||
with:
|
||||
subject-path: out/ArchiSteamFarm.OfficialPlugins.Monitoring.zip
|
||||
|
||||
- name: Upload ArchiSteamFarm.OfficialPlugins.Monitoring
|
||||
if: ${{ matrix.os == 'ubuntu-latest' && matrix.variant == 'generic' }}
|
||||
uses: actions/upload-artifact@v4.4.3
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ArchiSteamFarm.OfficialPlugins.Monitoring
|
||||
path: out/ArchiSteamFarm.OfficialPlugins.Monitoring.zip
|
||||
|
||||
release:
|
||||
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
|
||||
needs: publish-asf
|
||||
environment: release-github
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
attestations: write
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4.1.1
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
|
||||
- name: Download ASF-generic artifact from ubuntu-latest
|
||||
uses: actions/download-artifact@v4.1.4
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: ubuntu-latest_ASF-generic
|
||||
path: out
|
||||
|
||||
- name: Download ASF-linux-arm artifact from ubuntu-latest
|
||||
uses: actions/download-artifact@v4.1.4
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: ubuntu-latest_ASF-linux-arm
|
||||
path: out
|
||||
|
||||
- name: Download ASF-linux-arm64 artifact from ubuntu-latest
|
||||
uses: actions/download-artifact@v4.1.4
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: ubuntu-latest_ASF-linux-arm64
|
||||
path: out
|
||||
|
||||
- name: Download ASF-linux-x64 artifact from ubuntu-latest
|
||||
uses: actions/download-artifact@v4.1.4
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: ubuntu-latest_ASF-linux-x64
|
||||
path: out
|
||||
|
||||
- name: Download ASF-osx-arm64 artifact from macos-latest
|
||||
uses: actions/download-artifact@v4.1.4
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: macos-latest_ASF-osx-arm64
|
||||
path: out
|
||||
|
||||
- name: Download ASF-osx-x64 artifact from macos-latest
|
||||
uses: actions/download-artifact@v4.1.4
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: macos-latest_ASF-osx-x64
|
||||
path: out
|
||||
|
||||
- name: Download ASF-win-arm64 artifact from windows-latest
|
||||
uses: actions/download-artifact@v4.1.4
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: windows-latest_ASF-win-arm64
|
||||
path: out
|
||||
|
||||
- name: Download ASF-win-x64 artifact from windows-latest
|
||||
uses: actions/download-artifact@v4.1.4
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: windows-latest_ASF-win-x64
|
||||
path: out
|
||||
|
||||
- name: Download ArchiSteamFarm.OfficialPlugins.Monitoring artifact
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: ArchiSteamFarm.OfficialPlugins.Monitoring
|
||||
path: out
|
||||
|
||||
- name: Import GPG key for signing
|
||||
uses: crazy-max/ghaction-import-gpg@v6.1.0
|
||||
uses: crazy-max/ghaction-import-gpg@v6.2.0
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.ARCHIBOT_GPG_PRIVATE_KEY }}
|
||||
|
||||
- name: Generate SHA-512 checksums and signature
|
||||
shell: sh
|
||||
working-directory: out
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
(
|
||||
cd "out"
|
||||
sha512sum *.zip > SHA512SUMS
|
||||
gpg -a -b -o SHA512SUMS.sign SHA512SUMS
|
||||
|
||||
sha512sum *.zip > SHA512SUMS
|
||||
gpg -a -b -o SHA512SUMS.sign SHA512SUMS
|
||||
)
|
||||
- name: Generate artifact attestation for SHA512SUMS
|
||||
uses: actions/attest-build-provenance@v1.4.4
|
||||
with:
|
||||
subject-path: out/SHA512SUMS
|
||||
|
||||
- name: Upload SHA512SUMS
|
||||
uses: actions/upload-artifact@v4.3.1
|
||||
uses: actions/upload-artifact@v4.4.3
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: SHA512SUMS
|
||||
path: out/SHA512SUMS
|
||||
|
||||
- name: Upload SHA512SUMS.sign
|
||||
uses: actions/upload-artifact@v4.3.1
|
||||
- name: Generate artifact attestation for SHA512SUMS.sign
|
||||
uses: actions/attest-build-provenance@v1.4.4
|
||||
with:
|
||||
subject-path: out/SHA512SUMS.sign
|
||||
|
||||
- name: Upload SHA512SUMS.sign
|
||||
uses: actions/upload-artifact@v4.4.3
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: SHA512SUMS.sign
|
||||
path: out/SHA512SUMS.sign
|
||||
|
||||
- name: Create ArchiSteamFarm GitHub release
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
allowUpdates: true
|
||||
artifactErrorsFailBuild: true
|
||||
artifacts: "out/*"
|
||||
bodyFile: .github/RELEASE_TEMPLATE.md
|
||||
makeLatest: false
|
||||
name: ArchiSteamFarm V${{ github.ref_name }}
|
||||
prerelease: true
|
||||
token: ${{ secrets.ARCHIBOT_GITHUB_TOKEN }}
|
||||
updateOnlyUnreleased: true
|
||||
|
||||
36
.github/workflows/translations.yml
vendored
36
.github/workflows/translations.yml
vendored
@@ -3,17 +3,19 @@ name: ASF-translations
|
||||
on:
|
||||
schedule:
|
||||
- cron: '55 1 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
update:
|
||||
environment: dev-crowdin
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4.1.1
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
show-progress: false
|
||||
submodules: recursive
|
||||
@@ -21,16 +23,15 @@ jobs:
|
||||
|
||||
- name: Reset wiki to follow origin
|
||||
shell: sh
|
||||
working-directory: wiki
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
cd wiki
|
||||
|
||||
git fetch --depth=1 origin master
|
||||
git reset --hard origin/master
|
||||
|
||||
- name: Download latest translations from Crowdin
|
||||
uses: crowdin/github-action@v1.19.0
|
||||
uses: crowdin/github-action@v2.3.0
|
||||
with:
|
||||
upload_sources: false
|
||||
download_translations: true
|
||||
@@ -42,35 +43,28 @@ jobs:
|
||||
token: ${{ secrets.ASF_CROWDIN_API_TOKEN }}
|
||||
|
||||
- name: Import GPG key for signing
|
||||
uses: crazy-max/ghaction-import-gpg@v6.1.0
|
||||
uses: crazy-max/ghaction-import-gpg@v6.2.0
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.ARCHIBOT_GPG_PRIVATE_KEY }}
|
||||
git_config_global: true
|
||||
git_user_signingkey: true
|
||||
git_commit_gpgsign: true
|
||||
|
||||
- name: Commit the changes to wiki
|
||||
- name: Commit and push the changes to wiki
|
||||
shell: sh
|
||||
working-directory: wiki
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
cd wiki
|
||||
|
||||
git add -A "locale"
|
||||
|
||||
if ! git diff --cached --quiet; then
|
||||
git commit -m "Automatic translations update"
|
||||
|
||||
git push origin HEAD:master
|
||||
fi
|
||||
|
||||
- name: Push changes to wiki
|
||||
uses: ad-m/github-push-action@v0.8.0
|
||||
with:
|
||||
github_token: ${{ secrets.ARCHIBOT_GITHUB_TOKEN }}
|
||||
branch: master
|
||||
directory: wiki
|
||||
repository: ${{ github.repository }}.wiki
|
||||
|
||||
- name: Commit the changes to ASF
|
||||
- name: Commit and push the changes to ASF
|
||||
shell: sh
|
||||
run: |
|
||||
set -eu
|
||||
@@ -79,10 +73,6 @@ jobs:
|
||||
|
||||
if ! git diff --cached --quiet; then
|
||||
git commit -m "Automatic translations update"
|
||||
fi
|
||||
|
||||
- name: Push changes to ASF
|
||||
uses: ad-m/github-push-action@v0.8.0
|
||||
with:
|
||||
github_token: ${{ secrets.ARCHIBOT_GITHUB_TOKEN }}
|
||||
branch: ${{ github.ref }}
|
||||
git push
|
||||
fi
|
||||
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -543,3 +543,12 @@ $RECYCLE.BIN/
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# _ ____ _____
|
||||
# / \ / ___| | ___|
|
||||
# / _ \ \___ \ | |_
|
||||
# / ___ \ ___) || _|
|
||||
# /_/ \_\|____/ |_|
|
||||
|
||||
# Files that could be ignored by above rules, that we want to ship
|
||||
!ArchiSteamFarm/overlay/**
|
||||
|
||||
2
ASF-ui
2
ASF-ui
Submodule ASF-ui updated: b241705d0e...1f0b1914a4
@@ -4,7 +4,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ConfigureAwaitChecker.Analyzer" PrivateAssets="all" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="all" />
|
||||
<PackageReference Include="SteamKit2" IncludeAssets="compile" />
|
||||
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
|
||||
|
||||
@@ -34,6 +34,7 @@ using ArchiSteamFarm.Core;
|
||||
using ArchiSteamFarm.Plugins.Interfaces;
|
||||
using ArchiSteamFarm.Steam;
|
||||
using ArchiSteamFarm.Steam.Data;
|
||||
using ArchiSteamFarm.Steam.Exchange;
|
||||
using SteamKit2;
|
||||
|
||||
namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin;
|
||||
@@ -45,7 +46,7 @@ namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin;
|
||||
// If you do not want to handle a particular action (e.g. OnBotMessage that is offered in IBotMessage), it's the best idea to not inherit it at all
|
||||
// This will keep your code compact, efficient and less dependent. You can always add additional interfaces when you'll need them, this example project will inherit quite a bit of them to show you potential usage
|
||||
[SuppressMessage("ReSharper", "MemberCanBeFileLocal")]
|
||||
internal sealed class ExamplePlugin : IASF, IBot, IBotCommand2, IBotConnection, IBotFriendRequest, IBotMessage, IBotModules, IBotTradeOffer {
|
||||
internal sealed class ExamplePlugin : IASF, IBot, IBotCommand2, IBotConnection, IBotFriendRequest, IBotMessage, IBotModules, IBotTradeOffer2 {
|
||||
// This is used for identification purposes, typically you want to use a friendly name of your plugin here, such as the name of your main class
|
||||
// Please note that this property can have direct dependencies only on structures that were initialized by the constructor, as it's possible to be called before OnLoaded() takes place
|
||||
[JsonInclude]
|
||||
@@ -173,14 +174,14 @@ internal sealed class ExamplePlugin : IASF, IBot, IBotCommand2, IBotConnection,
|
||||
// If this message doesn't come from one of our bots, we can reply to the user in some pre-defined way
|
||||
bot.ArchiLogger.LogGenericTrace("Hey boss, we got some unknown message here!");
|
||||
|
||||
return Task.FromResult((string?) "I didn't get that, did you mean to use a command?");
|
||||
return Task.FromResult<string?>("I didn't get that, did you mean to use a command?");
|
||||
}
|
||||
|
||||
// This method is called when bot receives a trade offer that ASF isn't willing to accept (ignored and rejected trades)
|
||||
// It allows you not only to analyze such trades, but generate a response whether ASF should accept it (true), or proceed like usual (false)
|
||||
// Thanks to that, you can implement custom rules for all trades that aren't handled by ASF, for example cross-set trading on your own custom rules
|
||||
// You'd implement your own logic here, as an example we'll allow all trades to be accepted if the bot's name starts from "TrashBot"
|
||||
public Task<bool> OnBotTradeOffer(Bot bot, TradeOffer tradeOffer) => Task.FromResult(bot.BotName.StartsWith("TrashBot", StringComparison.OrdinalIgnoreCase));
|
||||
public Task<bool> OnBotTradeOffer(Bot bot, TradeOffer tradeOffer, ParseTradeResult.EResult asfResult) => Task.FromResult(bot.BotName.StartsWith("TrashBot", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
// This is the earliest method that will be called, right after loading the plugin, long before any bot initialization takes place
|
||||
// It's a good place to initialize all potential (non-bot-specific) structures that you will need across lifetime of your plugin, such as global timers, concurrent dictionaries and alike
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ConfigureAwaitChecker.Analyzer" PrivateAssets="all" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="all" />
|
||||
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AngleSharp.XPath" IncludeAssets="compile" />
|
||||
<PackageReference Include="ConfigureAwaitChecker.Analyzer" PrivateAssets="all" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="all" />
|
||||
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
//
|
||||
// |
|
||||
// Copyright 2015-2024 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
//
|
||||
// |
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// |
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// |
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
//
|
||||
// |
|
||||
// Copyright 2015-2024 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
//
|
||||
// |
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// |
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// |
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
//
|
||||
// |
|
||||
// Copyright 2015-2024 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
//
|
||||
// |
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// |
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// |
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
//
|
||||
// |
|
||||
// Copyright 2015-2024 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
//
|
||||
// |
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// |
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// |
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -22,7 +22,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
@@ -53,7 +52,7 @@ public sealed class SignInWithSteamController : ArchiController {
|
||||
Bot? bot = Bot.GetBot(botName);
|
||||
|
||||
if (bot == null) {
|
||||
return BadRequest(new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botName)));
|
||||
return BadRequest(new GenericResponse(false, Strings.FormatBotNotFound(botName)));
|
||||
}
|
||||
|
||||
if (!bot.IsConnectedAndLoggedOn) {
|
||||
@@ -64,7 +63,7 @@ public sealed class SignInWithSteamController : ArchiController {
|
||||
using HtmlDocumentResponse? challengeResponse = await bot.ArchiWebHandler.UrlGetToHtmlDocumentWithSession(request.RedirectURL).ConfigureAwait(false);
|
||||
|
||||
if (challengeResponse?.Content == null) {
|
||||
return StatusCode((int) HttpStatusCode.ServiceUnavailable, new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries)));
|
||||
return StatusCode((int) HttpStatusCode.ServiceUnavailable, new GenericResponse(false, Strings.FormatErrorRequestFailedTooManyTimes(WebBrowser.MaxTries)));
|
||||
}
|
||||
|
||||
IAttr? paramsNode = challengeResponse.Content.SelectSingleNode<IAttr>("//input[@name='openidparams']/@value");
|
||||
@@ -72,7 +71,7 @@ public sealed class SignInWithSteamController : ArchiController {
|
||||
if (paramsNode == null) {
|
||||
ASF.ArchiLogger.LogNullError(paramsNode);
|
||||
|
||||
return StatusCode((int) HttpStatusCode.InternalServerError, new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(paramsNode))));
|
||||
return StatusCode((int) HttpStatusCode.InternalServerError, new GenericResponse(false, Strings.FormatErrorObjectIsNull(nameof(paramsNode))));
|
||||
}
|
||||
|
||||
string paramsValue = paramsNode.Value;
|
||||
@@ -80,7 +79,7 @@ public sealed class SignInWithSteamController : ArchiController {
|
||||
if (string.IsNullOrEmpty(paramsValue)) {
|
||||
ASF.ArchiLogger.LogNullError(paramsValue);
|
||||
|
||||
return StatusCode((int) HttpStatusCode.InternalServerError, new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(paramsValue))));
|
||||
return StatusCode((int) HttpStatusCode.InternalServerError, new GenericResponse(false, Strings.FormatErrorObjectIsNull(nameof(paramsValue))));
|
||||
}
|
||||
|
||||
IAttr? nonceNode = challengeResponse.Content.SelectSingleNode<IAttr>("//input[@name='nonce']/@value");
|
||||
@@ -88,7 +87,7 @@ public sealed class SignInWithSteamController : ArchiController {
|
||||
if (nonceNode == null) {
|
||||
ASF.ArchiLogger.LogNullError(nonceNode);
|
||||
|
||||
return StatusCode((int) HttpStatusCode.InternalServerError, new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(nonceNode))));
|
||||
return StatusCode((int) HttpStatusCode.InternalServerError, new GenericResponse(false, Strings.FormatErrorObjectIsNull(nameof(nonceNode))));
|
||||
}
|
||||
|
||||
string nonceValue = nonceNode.Value;
|
||||
@@ -96,7 +95,7 @@ public sealed class SignInWithSteamController : ArchiController {
|
||||
if (string.IsNullOrEmpty(nonceValue)) {
|
||||
ASF.ArchiLogger.LogNullError(nonceValue);
|
||||
|
||||
return StatusCode((int) HttpStatusCode.InternalServerError, new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(nonceValue))));
|
||||
return StatusCode((int) HttpStatusCode.InternalServerError, new GenericResponse(false, Strings.FormatErrorObjectIsNull(nameof(nonceValue))));
|
||||
}
|
||||
|
||||
Uri loginRequest = new(ArchiWebHandler.SteamCommunityURL, "/openid/login");
|
||||
@@ -116,6 +115,6 @@ public sealed class SignInWithSteamController : ArchiController {
|
||||
// Accept OpenID request presented and follow redirection back to the data we initially expected
|
||||
BasicResponse? loginResponse = await bot.ArchiWebHandler.WebBrowser.UrlPost(loginRequest, data: data, requestOptions: WebBrowser.ERequestOptions.ReturnRedirections).ConfigureAwait(false);
|
||||
|
||||
return loginResponse != null ? Ok(new GenericResponse<SignInWithSteamResponse>(new SignInWithSteamResponse(loginResponse.FinalUri))) : StatusCode((int) HttpStatusCode.ServiceUnavailable, new GenericResponse(false, string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries)));
|
||||
return loginResponse != null ? Ok(new GenericResponse<SignInWithSteamResponse>(new SignInWithSteamResponse(loginResponse.FinalUri))) : StatusCode((int) HttpStatusCode.ServiceUnavailable, new GenericResponse(false, Strings.FormatErrorRequestFailedTooManyTimes(WebBrowser.MaxTries)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
//
|
||||
// |
|
||||
// Copyright 2015-2024 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
//
|
||||
// |
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// |
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// |
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ConfigureAwaitChecker.Analyzer" PrivateAssets="all" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.ResxSourceGenerator" PrivateAssets="all" />
|
||||
<PackageReference Include="SteamKit2" IncludeAssets="compile" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" IncludeAssets="compile" />
|
||||
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
|
||||
@@ -17,17 +17,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Localization\Strings.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Strings.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Localization\Strings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Strings.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<EmbeddedResource Update="Localization\Strings.resx" EmitFormatMethods="true" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -203,7 +203,7 @@ internal static class Backend {
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfEqual(requestID, Guid.Empty);
|
||||
|
||||
if (SharedInfo.BuildInfo.IsCustomBuild) {
|
||||
if (BuildInfo.IsCustomBuild) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
@@ -135,7 +134,7 @@ internal sealed class BotCache : SerializableFile {
|
||||
string json = await File.ReadAllTextAsync(filePath).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(json)) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json)));
|
||||
ASF.ArchiLogger.LogGenericError(Strings.FormatErrorIsEmpty(nameof(json)));
|
||||
|
||||
return new BotCache(filePath);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.Core;
|
||||
@@ -87,15 +86,15 @@ internal static class Commands {
|
||||
}
|
||||
|
||||
if (bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchEverything)) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(BotConfig.ETradingPreferences.MatchEverything)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(BotConfig.ETradingPreferences.MatchEverything)));
|
||||
}
|
||||
|
||||
if ((ASF.GlobalConfig?.LicenseID == null) || (ASF.GlobalConfig.LicenseID == Guid.Empty)) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(ASF.GlobalConfig.LicenseID)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(ASF.GlobalConfig.LicenseID)));
|
||||
}
|
||||
|
||||
if (!ItemsMatcherPlugin.RemoteCommunications.TryGetValue(bot, out RemoteCommunication? remoteCommunication)) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(remoteCommunication)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(remoteCommunication)));
|
||||
}
|
||||
|
||||
remoteCommunication.TriggerMatchActivelyEarlier();
|
||||
@@ -117,12 +116,12 @@ internal static class Commands {
|
||||
HashSet<Bot>? bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return access >= EAccess.Owner ? Steam.Interaction.Commands.FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null;
|
||||
return access >= EAccess.Owner ? Steam.Interaction.Commands.FormatStaticResponse(Strings.FormatBotNotFound(botNames)) : null;
|
||||
}
|
||||
|
||||
IList<string?> results = await Utilities.InParallel(bots.Select(bot => Task.Run(() => ResponseMatch(Steam.Interaction.Commands.GetProxyAccess(bot, access, steamID), bot)))).ConfigureAwait(false);
|
||||
|
||||
List<string> responses = [..results.Where(static result => !string.IsNullOrEmpty(result))];
|
||||
List<string> responses = [..results.Where(static result => !string.IsNullOrEmpty(result))!];
|
||||
|
||||
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@ internal class AssetInInventory : AssetForMatching {
|
||||
AssetID = asset.AssetID;
|
||||
}
|
||||
|
||||
internal Asset ToAsset() => new(Asset.SteamAppID, Asset.SteamCommunityContextID, ClassID, Amount, new InventoryDescription(Asset.SteamAppID, ClassID, tradable: false, realAppID: RealAppID, type: Type, rarity: Rarity), AssetID);
|
||||
internal Asset ToAsset() => new(Asset.SteamAppID, Asset.SteamCommunityContextID, ClassID, Amount, new InventoryDescription(Asset.SteamAppID, ClassID, tradable: Tradable, realAppID: RealAppID, type: Type, rarity: Rarity), AssetID);
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ArchiSteamFarm.OfficialPlugins.ItemsMatcher.Localization {
|
||||
using System;
|
||||
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Strings {
|
||||
|
||||
private static System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Strings() {
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.Equals(null, resourceMan)) {
|
||||
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ArchiSteamFarm.OfficialPlugins.ItemsMatcher.Localization.Strings", typeof(Strings).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal static string ActivelyMatchingItemsRound {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivelyMatchingItemsRound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string ListingAnnouncing {
|
||||
get {
|
||||
return ResourceManager.GetString("ListingAnnouncing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string MatchingFound {
|
||||
get {
|
||||
return ResourceManager.GetString("MatchingFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string TradeOfferFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("TradeOfferFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string ActivelyMatchingSomeConfirmationsFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivelyMatchingSomeConfirmationsFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingSomeConfirmationsFailed" xml:space="preserve">
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns="" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,19 +53,21 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
<value>در این دور جمعاً {0} ست مطابقت داده شد.</value>
|
||||
<comment>{0} will be replaced by number of sets traded</comment>
|
||||
</data>
|
||||
<data name="ListingAnnouncing" xml:space="preserve">
|
||||
<value>اینونتوری {0}({1}) دارای {2} آیتم است...</value>
|
||||
<comment>{0} will be replaced by steam ID (number), {1} will be replaced by user's nickname, {2} will be replaced with number of items in the inventory</comment>
|
||||
</data>
|
||||
<data name="MatchingFound" xml:space="preserve">
|
||||
<value>در مجموع {0} مورد با ربات {1} ({2}) مطابقت داده شد، درحال ارسال ترید...</value>
|
||||
<comment>{0} will be replaced by number of items matched, {1} will be replaced by steam ID (number), {2} will be replaced by user's nickname</comment>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,19 +53,29 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
<value>{0} sets ont été matché pendant ce round.</value>
|
||||
<comment>{0} will be replaced by number of sets traded</comment>
|
||||
</data>
|
||||
<data name="ListingAnnouncing" xml:space="preserve">
|
||||
<value>Annonce de {0} ({1}) avec l'inventaire réalisé à partir de {2} au total sur la liste...</value>
|
||||
<comment>{0} will be replaced by steam ID (number), {1} will be replaced by user's nickname, {2} will be replaced with number of items in the inventory</comment>
|
||||
</data>
|
||||
<data name="MatchingFound" xml:space="preserve">
|
||||
<value>Correspondance totale de {0} éléments avec le bot {1} ({2}), envoi de l'offre d'échange...</value>
|
||||
<comment>{0} will be replaced by number of items matched, {1} will be replaced by steam ID (number), {2} will be replaced by user's nickname</comment>
|
||||
</data>
|
||||
<data name="TradeOfferFailed" xml:space="preserve">
|
||||
<value>Impossible d'envoyer une offre d'échange au bot {0} ({1}), en cours ...</value>
|
||||
<comment>{0} will be replaced by steam ID (number), {1} will be replaced by user's nickname'</comment>
|
||||
</data>
|
||||
<data name="ActivelyMatchingSomeConfirmationsFailed" xml:space="preserve">
|
||||
<value>Certaines confirmations ont échoué, environ {0} sur les transactions {1} ont été envoyées avec succès.</value>
|
||||
<comment>{0} will be replaced by amount of the trade offers that succeeded (number), {1} will be replaced by amount of the trade offers that were supposed to be sent in total (number)</comment>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns="" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,17 +53,31 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
<value>Potivim un total de {0} in această rundă.</value>
|
||||
<comment>{0} will be replaced by number of sets traded</comment>
|
||||
</data>
|
||||
<data name="ListingAnnouncing" xml:space="preserve">
|
||||
<value>Anunțând {0} ({1}) cu inventarul făcut din {2} articole în total pe listă...</value>
|
||||
<comment>{0} will be replaced by steam ID (number), {1} will be replaced by user's nickname, {2} will be replaced with number of items in the inventory</comment>
|
||||
</data>
|
||||
<data name="MatchingFound" xml:space="preserve">
|
||||
<value>Se potrivește cu un total de {0} elemente cu botul {1} ({2}), se trimite oferta de schimb...</value>
|
||||
<comment>{0} will be replaced by number of items matched, {1} will be replaced by steam ID (number), {2} will be replaced by user's nickname</comment>
|
||||
</data>
|
||||
<data name="TradeOfferFailed" xml:space="preserve">
|
||||
<value>Nu s-a putut trimite o cerere de schimb bot-ului {0} ({1}), trecem peste...</value>
|
||||
<comment>{0} will be replaced by steam ID (number), {1} will be replaced by user's nickname'</comment>
|
||||
</data>
|
||||
<data name="ActivelyMatchingSomeConfirmationsFailed" xml:space="preserve">
|
||||
<value>Unele confirmări au eșuat, aproximativ {0} din {1} de schimburi au fost trimise cu succes.</value>
|
||||
<comment>{0} will be replaced by amount of the trade offers that succeeded (number), {1} will be replaced by amount of the trade offers that were supposed to be sent in total (number)</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<data name="ActivelyMatchingItemsRound" xml:space="preserve">
|
||||
|
||||
191
ArchiSteamFarm.OfficialPlugins.ItemsMatcher/MatchingUtilities.cs
Normal file
191
ArchiSteamFarm.OfficialPlugins.ItemsMatcher/MatchingUtilities.cs
Normal file
@@ -0,0 +1,191 @@
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// _ _ _ ____ _ _____
|
||||
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// |
|
||||
// Copyright 2015-2024 Łukasz "JustArchi" Domeradzki
|
||||
// Contact: JustArchi@JustArchi.net
|
||||
// |
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// |
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// |
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ArchiSteamFarm.Steam.Data;
|
||||
|
||||
namespace ArchiSteamFarm.OfficialPlugins.ItemsMatcher;
|
||||
|
||||
internal static class MatchingUtilities {
|
||||
internal static (Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> FullState, Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> TradableState) GetDividedInventoryState(IReadOnlyCollection<Asset> inventory) {
|
||||
if ((inventory == null) || (inventory.Count == 0)) {
|
||||
throw new ArgumentNullException(nameof(inventory));
|
||||
}
|
||||
|
||||
Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> fullState = new();
|
||||
Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> tradableState = new();
|
||||
|
||||
foreach (Asset item in inventory) {
|
||||
(uint RealAppID, EAssetType Type, EAssetRarity Rarity) key = (item.RealAppID, item.Type, item.Rarity);
|
||||
|
||||
if (fullState.TryGetValue(key, out Dictionary<ulong, uint>? fullSet)) {
|
||||
fullSet[item.ClassID] = fullSet.GetValueOrDefault(item.ClassID) + item.Amount;
|
||||
} else {
|
||||
fullState[key] = new Dictionary<ulong, uint> { { item.ClassID, item.Amount } };
|
||||
}
|
||||
|
||||
if (!item.Tradable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tradableState.TryGetValue(key, out Dictionary<ulong, uint>? tradableSet)) {
|
||||
tradableSet[item.ClassID] = tradableSet.GetValueOrDefault(item.ClassID) + item.Amount;
|
||||
} else {
|
||||
tradableState[key] = new Dictionary<ulong, uint> { { item.ClassID, item.Amount } };
|
||||
}
|
||||
}
|
||||
|
||||
return (fullState, tradableState);
|
||||
}
|
||||
|
||||
internal static Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> GetTradableInventoryState(IReadOnlyCollection<Asset> inventory) {
|
||||
if ((inventory == null) || (inventory.Count == 0)) {
|
||||
throw new ArgumentNullException(nameof(inventory));
|
||||
}
|
||||
|
||||
Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> tradableState = new();
|
||||
|
||||
foreach (Asset item in inventory.Where(static item => item.Tradable)) {
|
||||
(uint RealAppID, EAssetType Type, EAssetRarity Rarity) key = (item.RealAppID, item.Type, item.Rarity);
|
||||
|
||||
if (tradableState.TryGetValue(key, out Dictionary<ulong, uint>? tradableSet)) {
|
||||
tradableSet[item.ClassID] = tradableSet.GetValueOrDefault(item.ClassID) + item.Amount;
|
||||
} else {
|
||||
tradableState[key] = new Dictionary<ulong, uint> { { item.ClassID, item.Amount } };
|
||||
}
|
||||
}
|
||||
|
||||
return tradableState;
|
||||
}
|
||||
|
||||
internal static HashSet<Asset> GetTradableItemsFromInventory(IReadOnlyCollection<Asset> inventory, IReadOnlyDictionary<ulong, uint> classIDs, bool randomize = false) {
|
||||
if ((inventory == null) || (inventory.Count == 0)) {
|
||||
throw new ArgumentNullException(nameof(inventory));
|
||||
}
|
||||
|
||||
if ((classIDs == null) || (classIDs.Count == 0)) {
|
||||
throw new ArgumentNullException(nameof(classIDs));
|
||||
}
|
||||
|
||||
// We need a copy of classIDs passed since we're going to manipulate them
|
||||
Dictionary<ulong, uint> classIDsState = classIDs.ToDictionary();
|
||||
|
||||
HashSet<Asset> result = [];
|
||||
|
||||
IEnumerable<Asset> items = inventory.Where(static item => item.Tradable);
|
||||
|
||||
// Randomization helps to decrease "items no longer available" in regards to sending offers to other users
|
||||
if (randomize) {
|
||||
#pragma warning disable CA5394 // This call isn't used in a security-sensitive manner
|
||||
items = items.Where(item => classIDsState.ContainsKey(item.ClassID)).OrderBy(static _ => Random.Shared.Next());
|
||||
#pragma warning restore CA5394 // This call isn't used in a security-sensitive manner
|
||||
}
|
||||
|
||||
foreach (Asset item in items) {
|
||||
if (!classIDsState.TryGetValue(item.ClassID, out uint amount)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (amount >= item.Amount) {
|
||||
result.Add(item);
|
||||
|
||||
if (amount > item.Amount) {
|
||||
classIDsState[item.ClassID] = amount - item.Amount;
|
||||
} else {
|
||||
classIDsState.Remove(item.ClassID);
|
||||
|
||||
if (classIDsState.Count == 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Asset itemToAdd = item.DeepClone();
|
||||
|
||||
itemToAdd.Amount = amount;
|
||||
|
||||
result.Add(itemToAdd);
|
||||
|
||||
classIDsState.Remove(itemToAdd.ClassID);
|
||||
|
||||
if (classIDsState.Count == 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here it means we still have classIDs to match
|
||||
throw new InvalidOperationException(nameof(classIDs));
|
||||
}
|
||||
|
||||
internal static bool IsEmptyForMatching(IReadOnlyDictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> fullState, IReadOnlyDictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> tradableState) {
|
||||
ArgumentNullException.ThrowIfNull(fullState);
|
||||
ArgumentNullException.ThrowIfNull(tradableState);
|
||||
|
||||
foreach (((uint RealAppID, EAssetType Type, EAssetRarity Rarity) set, IReadOnlyDictionary<ulong, uint> state) in tradableState) {
|
||||
if (!fullState.TryGetValue(set, out Dictionary<ulong, uint>? fullSet) || (fullSet.Count == 0)) {
|
||||
throw new InvalidOperationException(nameof(fullSet));
|
||||
}
|
||||
|
||||
if (!IsEmptyForMatching(fullSet, state)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find any matchable combinations, so this inventory is empty
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static bool IsEmptyForMatching(IReadOnlyDictionary<ulong, uint> fullSet, IReadOnlyDictionary<ulong, uint> tradableSet) {
|
||||
ArgumentNullException.ThrowIfNull(fullSet);
|
||||
ArgumentNullException.ThrowIfNull(tradableSet);
|
||||
|
||||
foreach ((ulong classID, uint amount) in tradableSet) {
|
||||
switch (amount) {
|
||||
case 0:
|
||||
// No tradable items, this should never happen, dictionary should not have this key to begin with
|
||||
throw new InvalidOperationException(nameof(amount));
|
||||
case 1:
|
||||
// Single tradable item, can be matchable or not depending on the rest of the inventory
|
||||
if (!fullSet.TryGetValue(classID, out uint fullAmount) || (fullAmount == 0)) {
|
||||
throw new InvalidOperationException(nameof(fullAmount));
|
||||
}
|
||||
|
||||
if (fullAmount > 1) {
|
||||
// If we have a single tradable item but more than 1 in total, this is matchable
|
||||
return false;
|
||||
}
|
||||
|
||||
// A single exclusive tradable item is not matchable, continue
|
||||
continue;
|
||||
default:
|
||||
// Any other combination of tradable items is always matchable
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find any matchable combinations, so this inventory is empty
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -112,7 +111,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
TimeSpan.FromHours(6)
|
||||
);
|
||||
} else {
|
||||
bot.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningNoLicense, nameof(BotConfig.ETradingPreferences.MatchActively)));
|
||||
bot.ArchiLogger.LogGenericError(Strings.FormatWarningNoLicense(nameof(BotConfig.ETradingPreferences.MatchActively)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,7 +215,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
// This is actually network failure, so we'll stop sending heartbeats but not record it as valid check
|
||||
ShouldSendHeartBeats = false;
|
||||
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(IsEligibleForListing)}: {eligible?.ToString() ?? "null"}"));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError($"{nameof(IsEligibleForListing)}: {eligible?.ToString() ?? "null"}"));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -226,7 +225,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
LastAnnouncement = DateTime.UtcNow;
|
||||
ShouldSendAnnouncementEarlier = ShouldSendHeartBeats = false;
|
||||
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(IsEligibleForListing)}: {eligible.Value}"));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError($"{nameof(IsEligibleForListing)}: {eligible.Value}"));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -243,7 +242,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
// This is actually a network failure, so we'll stop sending heartbeats but not record it as valid check
|
||||
ShouldSendHeartBeats = false;
|
||||
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(tradeToken)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(nameof(tradeToken)));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -253,7 +252,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
|
||||
try {
|
||||
inventory = await Bot.ArchiHandler.GetMyInventoryAsync().ToListAsync().ConfigureAwait(false);
|
||||
} catch (HttpRequestException e) {
|
||||
} catch (TimeoutException e) {
|
||||
// This is actually a network failure, so we'll stop sending heartbeats but not record it as valid check
|
||||
ShouldSendHeartBeats = false;
|
||||
|
||||
@@ -396,17 +395,17 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
if (setPartsResponse == null) {
|
||||
// This is actually a network failure, so we'll stop sending heartbeats but not record it as valid check
|
||||
ShouldSendHeartBeats = false;
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(setPartsResponse)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatErrorObjectIsNull(nameof(setPartsResponse)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (setPartsResponse.StatusCode.IsRedirectionCode()) {
|
||||
ShouldSendHeartBeats = false;
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, setPartsResponse.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(setPartsResponse.StatusCode));
|
||||
|
||||
if (setPartsResponse.FinalUri.Host != ArchiWebHandler.SteamCommunityURL.Host) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(setPartsResponse.FinalUri), setPartsResponse.FinalUri));
|
||||
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(setPartsResponse.FinalUri), setPartsResponse.FinalUri));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -420,7 +419,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
if (!setPartsResponse.StatusCode.IsSuccessCode()) {
|
||||
// ArchiNet told us that we've sent a bad request, so the process should restart from the beginning at later time
|
||||
ShouldSendHeartBeats = false;
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, setPartsResponse.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(setPartsResponse.StatusCode));
|
||||
|
||||
switch (setPartsResponse.StatusCode) {
|
||||
case HttpStatusCode.Forbidden:
|
||||
@@ -443,7 +442,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
|
||||
if (setPartsResponse.Content?.Result == null) {
|
||||
// This should never happen if we got the correct response
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(setPartsResponse), setPartsResponse.Content?.Result));
|
||||
Bot.ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(setPartsResponse), setPartsResponse.Content?.Result));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -532,7 +531,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
// There is a possibility that our inventory has changed even if our announced assets did not, record that
|
||||
BotCache.LastInventoryChecksumBeforeDeduplication = inventoryChecksumBeforeDeduplication;
|
||||
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(assetsForListing)} > {MaxItemsCount}"));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError($"{nameof(assetsForListing)} > {MaxItemsCount}"));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -563,7 +562,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
|
||||
HashSet<AssetForListing> inventoryAddedChanged = assetsForListing.Where(asset => !previousInventoryState.Remove(asset.AssetID, out AssetForListing? previousAsset) || (asset.BackendHashCode != previousAsset.BackendHashCode)).ToHashSet();
|
||||
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Localization.Strings.ListingAnnouncing, Bot.SteamID, nickname ?? Bot.SteamID.ToString(CultureInfo.InvariantCulture), assetsForListing.Count));
|
||||
Bot.ArchiLogger.LogGenericInfo(Localization.Strings.FormatListingAnnouncing(Bot.SteamID, nickname ?? Bot.SteamID.ToString(CultureInfo.InvariantCulture), assetsForListing.Count));
|
||||
|
||||
ObjectResponse<GenericResponse<BackgroundTaskResponse>>? diffResponse = null;
|
||||
Guid diffRequestID = Guid.Empty;
|
||||
@@ -578,17 +577,17 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
if (diffResponse == null) {
|
||||
// This is actually a network failure, so we'll stop sending heartbeats but not record it as valid check
|
||||
ShouldSendHeartBeats = false;
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(diffResponse)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatErrorObjectIsNull(nameof(diffResponse)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (diffResponse.StatusCode.IsRedirectionCode()) {
|
||||
ShouldSendHeartBeats = false;
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, diffResponse.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(diffResponse.StatusCode));
|
||||
|
||||
if (diffResponse.FinalUri.Host != ArchiWebHandler.SteamCommunityURL.Host) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(diffResponse.FinalUri), diffResponse.FinalUri));
|
||||
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(diffResponse.FinalUri), diffResponse.FinalUri));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -602,7 +601,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
if (!diffResponse.StatusCode.IsSuccessCode()) {
|
||||
// ArchiNet told us that we've sent a bad request, so the process should restart from the beginning at later time
|
||||
ShouldSendHeartBeats = false;
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, diffResponse.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(diffResponse.StatusCode));
|
||||
|
||||
switch (diffResponse.StatusCode) {
|
||||
case HttpStatusCode.Conflict:
|
||||
@@ -631,7 +630,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
// Great, do we need to wait?
|
||||
if (diffResponse.Content?.Result == null) {
|
||||
// This should never happen if we got the correct response
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(diffResponse), diffResponse.Content?.Result));
|
||||
Bot.ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(diffResponse), diffResponse.Content?.Result));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -646,7 +645,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
|
||||
if (diffResponse == null) {
|
||||
// We've waited long enough, something is definitely wrong with us or the backend
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(diffResponse)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(nameof(diffResponse)));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -668,7 +667,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Localization.Strings.ListingAnnouncing, Bot.SteamID, nickname ?? Bot.SteamID.ToString(CultureInfo.InvariantCulture), assetsForListing.Count));
|
||||
Bot.ArchiLogger.LogGenericInfo(Localization.Strings.FormatListingAnnouncing(Bot.SteamID, nickname ?? Bot.SteamID.ToString(CultureInfo.InvariantCulture), assetsForListing.Count));
|
||||
|
||||
ObjectResponse<GenericResponse<BackgroundTaskResponse>>? announceResponse = null;
|
||||
Guid announceRequestID = Guid.Empty;
|
||||
@@ -683,17 +682,17 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
if (announceResponse == null) {
|
||||
// This is actually a network failure, so we'll stop sending heartbeats but not record it as valid check
|
||||
ShouldSendHeartBeats = false;
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(announceResponse)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatErrorObjectIsNull(nameof(announceResponse)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (announceResponse.StatusCode.IsRedirectionCode()) {
|
||||
ShouldSendHeartBeats = false;
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, announceResponse.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(announceResponse.StatusCode));
|
||||
|
||||
if (announceResponse.FinalUri.Host != ArchiWebHandler.SteamCommunityURL.Host) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(announceResponse.FinalUri), announceResponse.FinalUri));
|
||||
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(announceResponse.FinalUri), announceResponse.FinalUri));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -707,7 +706,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
if (!announceResponse.StatusCode.IsSuccessCode()) {
|
||||
// ArchiNet told us that we've sent a bad request, so the process should restart from the beginning at later time
|
||||
ShouldSendHeartBeats = false;
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, announceResponse.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(announceResponse.StatusCode));
|
||||
|
||||
switch (announceResponse.StatusCode) {
|
||||
case HttpStatusCode.Conflict:
|
||||
@@ -736,7 +735,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
// Great, do we need to wait?
|
||||
if (announceResponse.Content?.Result == null) {
|
||||
// This should never happen if we got the correct response
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(announceResponse), announceResponse.Content?.Result));
|
||||
Bot.ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(announceResponse), announceResponse.Content?.Result));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -751,7 +750,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
|
||||
if (announceResponse == null) {
|
||||
// We've waited long enough, something is definitely wrong with us or the backend
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(announceResponse)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(nameof(announceResponse)));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -802,7 +801,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
bool? hasPublicInventory = await Bot.HasPublicInventory().ConfigureAwait(false);
|
||||
|
||||
if (hasPublicInventory != true) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(Bot.HasPublicInventory)}: {hasPublicInventory?.ToString() ?? "null"}"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatWarningFailedWithError($"{nameof(Bot.HasPublicInventory)}: {hasPublicInventory?.ToString() ?? "null"}"));
|
||||
|
||||
return hasPublicInventory;
|
||||
}
|
||||
@@ -813,28 +812,28 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
private async Task<bool?> IsEligibleForMatching() {
|
||||
// Bot can't be limited
|
||||
if (Bot.IsAccountLimited) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(Bot.IsAccountLimited)}: {Bot.IsAccountLimited}"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatWarningFailedWithError($"{nameof(Bot.IsAccountLimited)}: {Bot.IsAccountLimited}"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bot can't be on lockdown
|
||||
if (Bot.IsAccountLocked) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(Bot.IsAccountLocked)}: {Bot.IsAccountLocked}"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatWarningFailedWithError($"{nameof(Bot.IsAccountLocked)}: {Bot.IsAccountLocked}"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bot must have ASF 2FA
|
||||
if (!Bot.HasMobileAuthenticator) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(Bot.HasMobileAuthenticator)}: {Bot.HasMobileAuthenticator}"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatWarningFailedWithError($"{nameof(Bot.HasMobileAuthenticator)}: {Bot.HasMobileAuthenticator}"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bot must have at least one accepted matchable type set
|
||||
if ((Bot.BotConfig.MatchableTypes.Count == 0) || Bot.BotConfig.MatchableTypes.All(static type => !AcceptedMatchableTypes.Contains(type))) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(Bot.BotConfig.MatchableTypes)}: {string.Join(", ", Bot.BotConfig.MatchableTypes)}"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatWarningFailedWithError($"{nameof(Bot.BotConfig.MatchableTypes)}: {string.Join(", ", Bot.BotConfig.MatchableTypes)}"));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -843,21 +842,21 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
CCredentials_GetSteamGuardDetails_Response? steamGuardStatus = await Bot.ArchiHandler.GetSteamGuardStatus().ConfigureAwait(false);
|
||||
|
||||
if (steamGuardStatus == null) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(steamGuardStatus)}: null"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatWarningFailedWithError($"{nameof(steamGuardStatus)}: null"));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Bot must have SteamGuard active for at least 15 days
|
||||
if (!steamGuardStatus.is_steamguard_enabled || ((steamGuardStatus.timestamp_steamguard_enabled > 0) && ((DateTimeOffset.UtcNow - DateTimeOffset.FromUnixTimeSeconds(steamGuardStatus.timestamp_steamguard_enabled)).TotalDays < MinimumSteamGuardEnabledDays))) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(steamGuardStatus.is_steamguard_enabled)}/{nameof(steamGuardStatus.timestamp_steamguard_enabled)}: {steamGuardStatus.is_steamguard_enabled}/{steamGuardStatus.timestamp_steamguard_enabled}"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatWarningFailedWithError($"{nameof(steamGuardStatus.is_steamguard_enabled)}/{nameof(steamGuardStatus.timestamp_steamguard_enabled)}: {steamGuardStatus.is_steamguard_enabled}/{steamGuardStatus.timestamp_steamguard_enabled}"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bot must have 2FA enabled for matching to work
|
||||
if (!steamGuardStatus.is_twofactor_enabled) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(steamGuardStatus.is_twofactor_enabled)}: false"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatWarningFailedWithError($"{nameof(steamGuardStatus.is_twofactor_enabled)}: false"));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -865,14 +864,14 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
CCredentials_LastCredentialChangeTime_Response? credentialChangeTimeDetails = await Bot.ArchiHandler.GetCredentialChangeTimeDetails().ConfigureAwait(false);
|
||||
|
||||
if (credentialChangeTimeDetails == null) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(credentialChangeTimeDetails)}: null"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatWarningFailedWithError($"{nameof(credentialChangeTimeDetails)}: null"));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Bot didn't change password in last 5 days
|
||||
if ((credentialChangeTimeDetails.timestamp_last_password_reset > 0) && ((DateTimeOffset.UtcNow - DateTimeOffset.FromUnixTimeSeconds(credentialChangeTimeDetails.timestamp_last_password_reset)).TotalDays < MinimumPasswordResetCooldownDays)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(credentialChangeTimeDetails.timestamp_last_password_reset)}: {credentialChangeTimeDetails.timestamp_last_password_reset}"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatWarningFailedWithError($"{nameof(credentialChangeTimeDetails.timestamp_last_password_reset)}: {credentialChangeTimeDetails.timestamp_last_password_reset}"));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -898,7 +897,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
bool? eligible = await IsEligibleForMatching().ConfigureAwait(false);
|
||||
|
||||
if (eligible != true) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(IsEligibleForMatching)}: {eligible?.ToString() ?? "null"}"));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError($"{nameof(IsEligibleForMatching)}: {eligible?.ToString() ?? "null"}"));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -925,13 +924,13 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
HttpStatusCode? licenseStatus = await Backend.GetLicenseStatus(ASF.GlobalConfig.LicenseID.Value, WebBrowser).ConfigureAwait(false);
|
||||
|
||||
if (licenseStatus == null) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(licenseStatus)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(nameof(licenseStatus)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!licenseStatus.Value.IsSuccessCode()) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, licenseStatus.Value));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(licenseStatus.Value));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -940,20 +939,20 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
|
||||
try {
|
||||
assetsForMatching = await Bot.ArchiHandler.GetMyInventoryAsync().Where(item => item is { AssetID: > 0, Amount: > 0, ClassID: > 0, RealAppID: > 0, Type: > EAssetType.Unknown, Rarity: > EAssetRarity.Unknown, IsSteamPointsShopItem: false } && acceptedMatchableTypes.Contains(item.Type) && !Bot.BotDatabase.MatchActivelyBlacklistAppIDs.Contains(item.RealAppID)).ToHashSetAsync().ConfigureAwait(false);
|
||||
} catch (HttpRequestException e) {
|
||||
} catch (TimeoutException e) {
|
||||
Bot.ArchiLogger.LogGenericWarningException(e);
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(assetsForMatching)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(nameof(assetsForMatching)));
|
||||
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
Bot.ArchiLogger.LogGenericException(e);
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(assetsForMatching)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(nameof(assetsForMatching)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (assetsForMatching.Count == 0) {
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(assetsForMatching)));
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.FormatErrorIsEmpty(nameof(assetsForMatching)));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -963,7 +962,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
|
||||
if (assetsForMatching.RemoveWhere(item => !setsToKeep.Contains((item.RealAppID, item.Type, item.Rarity))) > 0) {
|
||||
if (assetsForMatching.Count == 0) {
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(assetsForMatching)));
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.FormatErrorIsEmpty(nameof(assetsForMatching)));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1000,16 +999,16 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
|
||||
if (setPartsResponse == null) {
|
||||
// This is actually a network failure
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.ErrorObjectIsNull, nameof(setPartsResponse)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatErrorObjectIsNull(nameof(setPartsResponse)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (setPartsResponse.StatusCode.IsRedirectionCode()) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, setPartsResponse.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(setPartsResponse.StatusCode));
|
||||
|
||||
if (setPartsResponse.FinalUri.Host != ArchiWebHandler.SteamCommunityURL.Host) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(setPartsResponse.FinalUri), setPartsResponse.FinalUri));
|
||||
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(setPartsResponse.FinalUri), setPartsResponse.FinalUri));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1021,14 +1020,14 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
}
|
||||
|
||||
if (!setPartsResponse.StatusCode.IsSuccessCode()) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, setPartsResponse.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(setPartsResponse.StatusCode));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (setPartsResponse.Content?.Result == null) {
|
||||
// This should never happen if we got the correct response
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(setPartsResponse), setPartsResponse.Content?.Result));
|
||||
Bot.ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(setPartsResponse), setPartsResponse.Content?.Result));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1119,13 +1118,13 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
assetsForMatching = assetsForMatchingFiltered;
|
||||
|
||||
if (assetsForMatching.Count == 0) {
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(assetsForMatching)));
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.FormatErrorIsEmpty(nameof(assetsForMatching)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (assetsForMatching.Count > MaxItemsCount) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(assetsForMatching)} > {MaxItemsCount}"));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError($"{nameof(assetsForMatching)} > {MaxItemsCount}"));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1133,26 +1132,24 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
(HttpStatusCode StatusCode, ImmutableHashSet<ListedUser> Users)? response = await Backend.GetListedUsersForMatching(ASF.GlobalConfig.LicenseID.Value, Bot, WebBrowser, assetsForMatching, acceptedMatchableTypes).ConfigureAwait(false);
|
||||
|
||||
if (response == null) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(response)));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(nameof(response)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response.Value.StatusCode.IsSuccessCode()) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, response.Value.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(response.Value.StatusCode));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.Value.Users.IsEmpty) {
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(response.Value.Users)));
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.FormatErrorIsEmpty(nameof(response.Value.Users)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma warning disable CA2000 // False positive, we're actually wrapping it in the using clause below exactly for that purpose
|
||||
using (await Bot.Actions.GetTradingLock().ConfigureAwait(false)) {
|
||||
#pragma warning restore CA2000 // False positive, we're actually wrapping it in the using clause below exactly for that purpose
|
||||
tradesSent = await MatchActively(response.Value.Users, assetsForMatching, acceptedMatchableTypes).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -1167,7 +1164,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> MatchActively(IReadOnlyCollection<ListedUser> listedUsers, IReadOnlyCollection<Asset> ourAssets, IReadOnlyCollection<EAssetType> acceptedMatchableTypes) {
|
||||
private async Task<bool> MatchActively(ImmutableHashSet<ListedUser> listedUsers, HashSet<Asset> ourAssets, HashSet<EAssetType> acceptedMatchableTypes) {
|
||||
if ((listedUsers == null) || (listedUsers.Count == 0)) {
|
||||
throw new ArgumentNullException(nameof(listedUsers));
|
||||
}
|
||||
@@ -1180,11 +1177,11 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
throw new ArgumentNullException(nameof(acceptedMatchableTypes));
|
||||
}
|
||||
|
||||
(Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> ourFullState, Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> ourTradableState) = Trading.GetDividedInventoryState(ourAssets);
|
||||
(Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> ourFullState, Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> ourTradableState) = MatchingUtilities.GetDividedInventoryState(ourAssets);
|
||||
|
||||
if (Trading.IsEmptyForMatching(ourFullState, ourTradableState)) {
|
||||
if (MatchingUtilities.IsEmptyForMatching(ourFullState, ourTradableState)) {
|
||||
// User doesn't have any more dupes in the inventory
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, $"{nameof(ourFullState)} || {nameof(ourTradableState)}"));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatErrorIsEmpty($"{nameof(ourFullState)} || {nameof(ourTradableState)}"));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1250,9 +1247,17 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
byte failuresInRow = 0;
|
||||
uint matchedSets = 0;
|
||||
|
||||
foreach (ListedUser listedUser in listedUsers.Where(listedUser => (listedUser.SteamID != Bot.SteamID) && acceptedMatchableTypes.Any(listedUser.MatchableTypes.Contains) && !Bot.IsBlacklistedFromTrades(listedUser.SteamID)).OrderByDescending(listedUser => !deprioritizedSteamIDs.Contains(listedUser.SteamID)).ThenByDescending(static listedUser => listedUser.TotalGamesCount > 1).ThenByDescending(static listedUser => listedUser.MatchEverything).ThenBy(static listedUser => listedUser.TotalInventoryCount)) {
|
||||
HashSet<(uint RealAppID, EAssetType Type, EAssetRarity Rarity)> skippedSetsThisUser = [];
|
||||
HashSet<(uint RealAppID, EAssetType Type, EAssetRarity Rarity)> skippedSetsThisTrade = [];
|
||||
|
||||
Dictionary<ulong, uint> classIDsToGive = new();
|
||||
Dictionary<ulong, uint> classIDsToReceive = new();
|
||||
Dictionary<ulong, uint> fairClassIDsToGive = new();
|
||||
Dictionary<ulong, uint> fairClassIDsToReceive = new();
|
||||
|
||||
foreach (ListedUser listedUser in listedUsers.Where(listedUser => (listedUser.SteamID != Bot.SteamID) && acceptedMatchableTypes.Overlaps(listedUser.MatchableTypes) && !Bot.IsBlacklistedFromTrades(listedUser.SteamID)).OrderByDescending(listedUser => !deprioritizedSteamIDs.Contains(listedUser.SteamID)).ThenByDescending(static listedUser => listedUser.TotalGamesCount > 1).ThenByDescending(static listedUser => listedUser.MatchEverything).ThenBy(static listedUser => listedUser.TotalInventoryCount)) {
|
||||
if (failuresInRow >= WebBrowser.MaxTries) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{nameof(failuresInRow)} >= {WebBrowser.MaxTries}"));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError($"{nameof(failuresInRow)} >= {WebBrowser.MaxTries}"));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1275,7 +1280,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
|
||||
switch (tradeHoldDuration) {
|
||||
case null:
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(tradeHoldDuration)));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatErrorIsEmpty(nameof(tradeHoldDuration)));
|
||||
|
||||
continue;
|
||||
case > 0 when (tradeHoldDuration.Value > maxTradeHoldDuration) || (tradeHoldDuration.Value > listedUser.MaxTradeHoldDuration):
|
||||
@@ -1290,18 +1295,19 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
continue;
|
||||
}
|
||||
|
||||
HashSet<(uint RealAppID, EAssetType Type, EAssetRarity Rarity)> skippedSetsThisUser = [];
|
||||
skippedSetsThisUser.Clear();
|
||||
|
||||
Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> theirTradableState = Trading.GetTradableInventoryState(theirInventory);
|
||||
Dictionary<(uint RealAppID, EAssetType Type, EAssetRarity Rarity), Dictionary<ulong, uint>> theirTradableState = MatchingUtilities.GetTradableInventoryState(theirInventory);
|
||||
|
||||
for (byte i = 0; i < Trading.MaxTradesPerAccount; i++) {
|
||||
byte itemsInTrade = 0;
|
||||
HashSet<(uint RealAppID, EAssetType Type, EAssetRarity Rarity)> skippedSetsThisTrade = [];
|
||||
|
||||
Dictionary<ulong, uint> classIDsToGive = new();
|
||||
Dictionary<ulong, uint> classIDsToReceive = new();
|
||||
Dictionary<ulong, uint> fairClassIDsToGive = new();
|
||||
Dictionary<ulong, uint> fairClassIDsToReceive = new();
|
||||
skippedSetsThisTrade.Clear();
|
||||
|
||||
classIDsToGive.Clear();
|
||||
classIDsToReceive.Clear();
|
||||
fairClassIDsToGive.Clear();
|
||||
fairClassIDsToReceive.Clear();
|
||||
|
||||
foreach (((uint RealAppID, EAssetType Type, EAssetRarity Rarity) set, Dictionary<ulong, uint> ourFullItems) in ourFullState.Where(set => !skippedSetsThisUser.Contains(set.Key) && listedUser.MatchableTypes.Contains(set.Key.Type) && set.Value.Values.Any(static count => count > 1))) {
|
||||
if (!ourTradableState.TryGetValue(set, out Dictionary<ulong, uint>? ourTradableItems) || (ourTradableItems.Count == 0)) {
|
||||
@@ -1314,14 +1320,14 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Trading.IsEmptyForMatching(ourFullItems, ourTradableItems)) {
|
||||
if (MatchingUtilities.IsEmptyForMatching(ourFullItems, ourTradableItems)) {
|
||||
// We may have no more matchable items from this set
|
||||
continue;
|
||||
}
|
||||
|
||||
// Those 2 collections are on user-basis since we can't be sure that the trade passes through (and therefore we need to keep original state in case of a failure)
|
||||
Dictionary<ulong, uint> ourFullSet = new(ourFullItems);
|
||||
Dictionary<ulong, uint> ourTradableSet = new(ourTradableItems);
|
||||
Dictionary<ulong, uint> ourFullSet = ourFullItems.ToDictionary();
|
||||
Dictionary<ulong, uint> ourTradableSet = ourTradableItems.ToDictionary();
|
||||
|
||||
bool match;
|
||||
|
||||
@@ -1347,13 +1353,13 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
fairClassIDsToReceive[theirItem] = ++fairReceivedAmount;
|
||||
|
||||
// Filter their inventory for the sets we're trading or have traded with this user
|
||||
HashSet<Asset> fairFiltered = theirInventory.Where(item => ((item.RealAppID == set.RealAppID) && (item.Type == set.Type) && (item.Rarity == set.Rarity)) || skippedSetsThisTrade.Contains((item.RealAppID, item.Type, item.Rarity))).Select(static item => item.CreateShallowCopy()).ToHashSet();
|
||||
HashSet<Asset> fairFiltered = theirInventory.Where(item => ((item.RealAppID == set.RealAppID) && (item.Type == set.Type) && (item.Rarity == set.Rarity)) || skippedSetsThisTrade.Contains((item.RealAppID, item.Type, item.Rarity))).ToHashSet();
|
||||
|
||||
// Copy list to HashSet<Steam.Asset>
|
||||
HashSet<Asset> fairItemsToGive = Trading.GetTradableItemsFromInventory(ourInventory.Values.Where(item => ((item.RealAppID == set.RealAppID) && (item.Type == set.Type) && (item.Rarity == set.Rarity)) || skippedSetsThisTrade.Contains((item.RealAppID, item.Type, item.Rarity))).Select(static item => item.CreateShallowCopy()).ToHashSet(), fairClassIDsToGive.ToDictionary(static classID => classID.Key, static classID => classID.Value));
|
||||
HashSet<Asset> fairItemsToReceive = Trading.GetTradableItemsFromInventory(fairFiltered.Select(static item => item.CreateShallowCopy()).ToHashSet(), fairClassIDsToReceive.ToDictionary(static classID => classID.Key, static classID => classID.Value));
|
||||
// Get tradable items from our and their inventory
|
||||
HashSet<Asset> fairItemsToGive = MatchingUtilities.GetTradableItemsFromInventory(ourInventory.Values.Where(item => ((item.RealAppID == set.RealAppID) && (item.Type == set.Type) && (item.Rarity == set.Rarity)) || skippedSetsThisTrade.Contains((item.RealAppID, item.Type, item.Rarity))).ToHashSet(), fairClassIDsToGive);
|
||||
HashSet<Asset> fairItemsToReceive = MatchingUtilities.GetTradableItemsFromInventory(fairFiltered, fairClassIDsToReceive);
|
||||
|
||||
// Actual check
|
||||
// Actual check, since we do this against remote user, we flip places for items
|
||||
if (!Trading.IsTradeNeutralOrBetter(fairFiltered, fairItemsToReceive, fairItemsToGive)) {
|
||||
// Revert the changes
|
||||
if (fairGivenAmount > 1) {
|
||||
@@ -1415,25 +1421,25 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
}
|
||||
|
||||
if (skippedSetsThisTrade.Count == 0) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(skippedSetsThisTrade)));
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.FormatErrorIsEmpty(nameof(skippedSetsThisTrade)));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove the items from inventories
|
||||
HashSet<Asset> itemsToGive = Trading.GetTradableItemsFromInventory(ourInventory.Values, classIDsToGive);
|
||||
HashSet<Asset> itemsToReceive = Trading.GetTradableItemsFromInventory(theirInventory, classIDsToReceive, true);
|
||||
HashSet<Asset> itemsToGive = MatchingUtilities.GetTradableItemsFromInventory(ourInventory.Values, classIDsToGive);
|
||||
HashSet<Asset> itemsToReceive = MatchingUtilities.GetTradableItemsFromInventory(theirInventory, classIDsToReceive, true);
|
||||
|
||||
if ((itemsToGive.Count != itemsToReceive.Count) || !Trading.IsFairExchange(itemsToGive, itemsToReceive)) {
|
||||
// Failsafe
|
||||
throw new InvalidOperationException($"{nameof(itemsToGive)} && {nameof(itemsToReceive)}");
|
||||
}
|
||||
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Localization.Strings.MatchingFound, itemsToReceive.Count, listedUser.SteamID, listedUser.Nickname));
|
||||
Bot.ArchiLogger.LogGenericInfo(Localization.Strings.FormatMatchingFound(itemsToReceive.Count, listedUser.SteamID, listedUser.Nickname));
|
||||
|
||||
Bot.ArchiLogger.LogGenericTrace($"{Bot.SteamID} <- {string.Join(", ", itemsToReceive.Select(static item => $"{item.RealAppID}/{item.Type}/{item.Rarity}/{item.ClassID} #{item.Amount}"))} | {string.Join(", ", itemsToGive.Select(static item => $"{item.RealAppID}/{item.Type}/{item.Rarity}/{item.ClassID} #{item.Amount}"))} -> {listedUser.SteamID}");
|
||||
|
||||
(bool success, HashSet<ulong>? tradeOfferIDs, HashSet<ulong>? mobileTradeOfferIDs) = await Bot.ArchiWebHandler.SendTradeOffer(listedUser.SteamID, itemsToGive, itemsToReceive, listedUser.TradeToken, true).ConfigureAwait(false);
|
||||
(bool success, HashSet<ulong>? tradeOfferIDs, HashSet<ulong>? mobileTradeOfferIDs) = await Bot.ArchiWebHandler.SendTradeOffer(listedUser.SteamID, itemsToGive, itemsToReceive, listedUser.TradeToken, nameof(MatchActively), true).ConfigureAwait(false);
|
||||
|
||||
if (tradeOfferIDs?.Count > 0) {
|
||||
matchActivelyTradeOfferIDs.UnionWith(tradeOfferIDs);
|
||||
@@ -1448,7 +1454,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
(bool twoFactorSuccess, IReadOnlyCollection<Confirmation>? handledConfirmations, _) = await Bot.Actions.HandleTwoFactorAuthenticationConfirmations(true, Confirmation.EConfirmationType.Trade, pendingMobileTradeOfferIDs, true).ConfigureAwait(false);
|
||||
|
||||
if (!twoFactorSuccess) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Localization.Strings.ActivelyMatchingSomeConfirmationsFailed, handledConfirmations?.Count ?? 0, pendingMobileTradeOfferIDs.Count));
|
||||
Bot.ArchiLogger.LogGenericWarning(Localization.Strings.FormatActivelyMatchingSomeConfirmationsFailed(handledConfirmations?.Count ?? 0, pendingMobileTradeOfferIDs.Count));
|
||||
}
|
||||
|
||||
pendingMobileTradeOfferIDs.Clear();
|
||||
@@ -1459,7 +1465,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
// The user likely no longer has the items we need, this is fine, we can continue the matching with other ones
|
||||
failuresInRow++;
|
||||
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Localization.Strings.TradeOfferFailed, listedUser.SteamID, listedUser.Nickname));
|
||||
Bot.ArchiLogger.LogGenericWarning(Localization.Strings.FormatTradeOfferFailed(listedUser.SteamID, listedUser.Nickname));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1534,7 +1540,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
|
||||
matchedSets += (uint) skippedSetsThisUser.Count;
|
||||
|
||||
if (Trading.IsEmptyForMatching(ourFullState, ourTradableState)) {
|
||||
if (MatchingUtilities.IsEmptyForMatching(ourFullState, ourTradableState)) {
|
||||
// User doesn't have any more dupes in the inventory
|
||||
break;
|
||||
}
|
||||
@@ -1544,11 +1550,11 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
(bool twoFactorSuccess, IReadOnlyCollection<Confirmation>? handledConfirmations, _) = Bot.IsConnectedAndLoggedOn ? await Bot.Actions.HandleTwoFactorAuthenticationConfirmations(true, Confirmation.EConfirmationType.Trade, pendingMobileTradeOfferIDs, true).ConfigureAwait(false) : (false, null, null);
|
||||
|
||||
if (!twoFactorSuccess) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Localization.Strings.ActivelyMatchingSomeConfirmationsFailed, handledConfirmations?.Count ?? 0, pendingMobileTradeOfferIDs.Count));
|
||||
Bot.ArchiLogger.LogGenericWarning(Localization.Strings.FormatActivelyMatchingSomeConfirmationsFailed(handledConfirmations?.Count ?? 0, pendingMobileTradeOfferIDs.Count));
|
||||
}
|
||||
}
|
||||
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(CultureInfo.CurrentCulture, Localization.Strings.ActivelyMatchingItemsRound, matchedSets));
|
||||
Bot.ArchiLogger.LogGenericInfo(Localization.Strings.FormatActivelyMatchingItemsRound(matchedSets));
|
||||
|
||||
return matchedSets > 0;
|
||||
}
|
||||
@@ -1604,10 +1610,10 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
if (response.StatusCode.IsRedirectionCode()) {
|
||||
ShouldSendHeartBeats = false;
|
||||
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, response.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(response.StatusCode));
|
||||
|
||||
if (response.FinalUri.Host != ArchiWebHandler.SteamCommunityURL.Host) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.WarningUnknownValuePleaseReport, nameof(response.FinalUri), response.FinalUri));
|
||||
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningUnknownValuePleaseReport(nameof(response.FinalUri), response.FinalUri));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1623,7 +1629,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
|
||||
if (!response.StatusCode.IsSuccessCode()) {
|
||||
ShouldSendHeartBeats = false;
|
||||
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, response.StatusCode));
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatWarningFailedWithError(response.StatusCode));
|
||||
|
||||
switch (response.StatusCode) {
|
||||
case HttpStatusCode.Conflict:
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ConfigureAwaitChecker.Analyzer" PrivateAssets="all" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.ResxSourceGenerator" PrivateAssets="all" />
|
||||
<PackageReference Include="SteamKit2" IncludeAssets="compile" />
|
||||
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
|
||||
</ItemGroup>
|
||||
@@ -15,17 +15,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Localization\Strings.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Strings.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Localization\Strings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Strings.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<EmbeddedResource Update="Localization\Strings.resx" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -38,8 +37,6 @@ using SteamKit2.Internal;
|
||||
namespace ArchiSteamFarm.OfficialPlugins.MobileAuthenticator;
|
||||
|
||||
internal static class Commands {
|
||||
private const byte MaxFinalizationAttempts = 900 / Steam.Security.MobileAuthenticator.CodeInterval;
|
||||
|
||||
internal static async Task<string?> OnBotCommand(Bot bot, EAccess access, string message, string[] args, ulong steamID = 0) {
|
||||
ArgumentNullException.ThrowIfNull(bot);
|
||||
|
||||
@@ -102,7 +99,7 @@ internal static class Commands {
|
||||
}
|
||||
|
||||
if (bot.HasMobileAuthenticator) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(bot.HasMobileAuthenticator)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(bot.HasMobileAuthenticator)));
|
||||
}
|
||||
|
||||
if (!bot.IsConnectedAndLoggedOn) {
|
||||
@@ -123,17 +120,17 @@ internal static class Commands {
|
||||
} catch (Exception e) {
|
||||
bot.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, e.Message));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(e.Message));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(json)) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatErrorIsEmpty(nameof(json)));
|
||||
}
|
||||
|
||||
Steam.Security.MobileAuthenticator? mobileAuthenticator = json.ToJsonObject<Steam.Security.MobileAuthenticator>();
|
||||
|
||||
if (mobileAuthenticator == null) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatErrorIsEmpty(nameof(json)));
|
||||
}
|
||||
|
||||
mobileAuthenticator.Init(bot);
|
||||
@@ -146,47 +143,26 @@ internal static class Commands {
|
||||
|
||||
ulong steamTime = await mobileAuthenticator.GetSteamTime().ConfigureAwait(false);
|
||||
|
||||
bool successFinalizing = false;
|
||||
string? code = mobileAuthenticator.GenerateTokenForTime(steamTime);
|
||||
|
||||
for (byte i = 0; i < MaxFinalizationAttempts; i++) {
|
||||
if (i > 0) {
|
||||
steamTime += Steam.Security.MobileAuthenticator.CodeInterval;
|
||||
}
|
||||
|
||||
string? code = mobileAuthenticator.GenerateTokenForTime(steamTime);
|
||||
|
||||
if (string.IsNullOrEmpty(code)) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(mobileAuthenticator.GenerateTokenForTime)));
|
||||
}
|
||||
|
||||
CTwoFactor_FinalizeAddAuthenticator_Response? response = await mobileAuthenticatorHandler.FinalizeAuthenticator(bot.SteamID, activationCode, code, steamTime).ConfigureAwait(false);
|
||||
|
||||
if (response == null) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(mobileAuthenticatorHandler.FinalizeAuthenticator)));
|
||||
}
|
||||
|
||||
if (response.want_more) {
|
||||
// OK, whatever
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!response.success) {
|
||||
EResult result = (EResult) response.status;
|
||||
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, result));
|
||||
}
|
||||
|
||||
successFinalizing = true;
|
||||
|
||||
break;
|
||||
if (string.IsNullOrEmpty(code)) {
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(mobileAuthenticator.GenerateTokenForTime)));
|
||||
}
|
||||
|
||||
if (!successFinalizing) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.ErrorRequestFailedTooManyTimes, MaxFinalizationAttempts));
|
||||
CTwoFactor_FinalizeAddAuthenticator_Response? response = await mobileAuthenticatorHandler.FinalizeAuthenticator(bot.SteamID, activationCode, code, steamTime).ConfigureAwait(false);
|
||||
|
||||
if (response == null) {
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(mobileAuthenticatorHandler.FinalizeAuthenticator)));
|
||||
}
|
||||
|
||||
if (!response.success) {
|
||||
EResult result = (EResult) response.status;
|
||||
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(result));
|
||||
}
|
||||
|
||||
if (!bot.TryImportAuthenticator(mobileAuthenticator)) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(bot.TryImportAuthenticator)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(bot.TryImportAuthenticator)));
|
||||
}
|
||||
|
||||
string maFileFinishedPath = $"{maFilePath}.NEW";
|
||||
@@ -196,7 +172,7 @@ internal static class Commands {
|
||||
} catch (Exception e) {
|
||||
bot.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, e.Message));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(e.Message));
|
||||
}
|
||||
|
||||
return bot.Commands.FormatBotResponse(Strings.Done);
|
||||
@@ -217,12 +193,12 @@ internal static class Commands {
|
||||
HashSet<Bot>? bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return access >= EAccess.Owner ? Steam.Interaction.Commands.FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null;
|
||||
return access >= EAccess.Owner ? Steam.Interaction.Commands.FormatStaticResponse(Strings.FormatBotNotFound(botNames)) : null;
|
||||
}
|
||||
|
||||
IList<string?> results = await Utilities.InParallel(bots.Select(bot => ResponseTwoFactorFinalize(Steam.Interaction.Commands.GetProxyAccess(bot, access, steamID), bot, activationCode))).ConfigureAwait(false);
|
||||
|
||||
List<string> responses = [..results.Where(static result => !string.IsNullOrEmpty(result))];
|
||||
List<string> responses = [..results.Where(static result => !string.IsNullOrEmpty(result))!];
|
||||
|
||||
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
|
||||
}
|
||||
@@ -239,7 +215,7 @@ internal static class Commands {
|
||||
}
|
||||
|
||||
if (bot.HasMobileAuthenticator) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(bot.HasMobileAuthenticator)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(bot.HasMobileAuthenticator)));
|
||||
}
|
||||
|
||||
string maFilePath = bot.GetFilePath(Bot.EFileType.MobileAuthenticator);
|
||||
@@ -256,17 +232,17 @@ internal static class Commands {
|
||||
} catch (Exception e) {
|
||||
bot.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, e.Message));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(e.Message));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(json)) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatErrorIsEmpty(nameof(json)));
|
||||
}
|
||||
|
||||
Steam.Security.MobileAuthenticator? mobileAuthenticator = json.ToJsonObject<Steam.Security.MobileAuthenticator>();
|
||||
|
||||
if (mobileAuthenticator == null) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatErrorIsEmpty(nameof(json)));
|
||||
}
|
||||
|
||||
mobileAuthenticator.Init(bot);
|
||||
@@ -274,13 +250,17 @@ internal static class Commands {
|
||||
if (!string.IsNullOrEmpty(activationCode)) {
|
||||
string? generatedCode = await mobileAuthenticator.GenerateToken().ConfigureAwait(false);
|
||||
|
||||
if (generatedCode != activationCode) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, $"{generatedCode} != {activationCode}"));
|
||||
if (string.IsNullOrEmpty(generatedCode)) {
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(generatedCode)));
|
||||
}
|
||||
|
||||
if (!generatedCode.Equals(activationCode, StringComparison.OrdinalIgnoreCase)) {
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError($"{generatedCode} != {activationCode}"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!bot.TryImportAuthenticator(mobileAuthenticator)) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(bot.TryImportAuthenticator)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(bot.TryImportAuthenticator)));
|
||||
}
|
||||
|
||||
string maFileFinishedPath = $"{maFilePath}.NEW";
|
||||
@@ -290,7 +270,7 @@ internal static class Commands {
|
||||
} catch (Exception e) {
|
||||
bot.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, e.Message));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(e.Message));
|
||||
}
|
||||
|
||||
return bot.Commands.FormatBotResponse(Strings.Done);
|
||||
@@ -310,12 +290,12 @@ internal static class Commands {
|
||||
HashSet<Bot>? bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return access >= EAccess.Owner ? Steam.Interaction.Commands.FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null;
|
||||
return access >= EAccess.Owner ? Steam.Interaction.Commands.FormatStaticResponse(Strings.FormatBotNotFound(botNames)) : null;
|
||||
}
|
||||
|
||||
IList<string?> results = await Utilities.InParallel(bots.Select(bot => ResponseTwoFactorFinalized(Steam.Interaction.Commands.GetProxyAccess(bot, access, steamID), bot, activationCode))).ConfigureAwait(false);
|
||||
|
||||
List<string> responses = [..results.Where(static result => !string.IsNullOrEmpty(result))];
|
||||
List<string> responses = [..results.Where(static result => !string.IsNullOrEmpty(result))!];
|
||||
|
||||
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
|
||||
}
|
||||
@@ -332,7 +312,7 @@ internal static class Commands {
|
||||
}
|
||||
|
||||
if (bot.HasMobileAuthenticator) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, nameof(bot.HasMobileAuthenticator)));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(nameof(bot.HasMobileAuthenticator)));
|
||||
}
|
||||
|
||||
if (!bot.IsConnectedAndLoggedOn) {
|
||||
@@ -356,7 +336,7 @@ internal static class Commands {
|
||||
EResult result = (EResult) response.status;
|
||||
|
||||
if (result != EResult.OK) {
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, result));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(result));
|
||||
}
|
||||
|
||||
MaFileData maFileData = new(response, bot.SteamID, deviceID);
|
||||
@@ -369,7 +349,7 @@ internal static class Commands {
|
||||
} catch (Exception e) {
|
||||
bot.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return bot.Commands.FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.WarningFailedWithError, e.Message));
|
||||
return bot.Commands.FormatBotResponse(Strings.FormatWarningFailedWithError(e.Message));
|
||||
}
|
||||
|
||||
return bot.Commands.FormatBotResponse(Strings.Done);
|
||||
@@ -389,12 +369,12 @@ internal static class Commands {
|
||||
HashSet<Bot>? bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return access >= EAccess.Owner ? Steam.Interaction.Commands.FormatStaticResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotNotFound, botNames)) : null;
|
||||
return access >= EAccess.Owner ? Steam.Interaction.Commands.FormatStaticResponse(Strings.FormatBotNotFound(botNames)) : null;
|
||||
}
|
||||
|
||||
IList<string?> results = await Utilities.InParallel(bots.Select(bot => ResponseTwoFactorInit(Steam.Interaction.Commands.GetProxyAccess(bot, access, steamID), bot))).ConfigureAwait(false);
|
||||
|
||||
List<string> responses = [..results.Where(static result => !string.IsNullOrEmpty(result))];
|
||||
List<string> responses = [..results.Where(static result => !string.IsNullOrEmpty(result))!];
|
||||
|
||||
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ArchiSteamFarm.OfficialPlugins.MobileAuthenticator.Localization {
|
||||
using System;
|
||||
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Strings {
|
||||
|
||||
private static System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Strings() {
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.Equals(null, resourceMan)) {
|
||||
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ArchiSteamFarm.OfficialPlugins.MobileAuthenticator.Localization.Strings", typeof(Strings).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns="" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns="" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
@@ -53,13 +53,11 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
|
||||
PublicKeyToken=b77a5c561934e089
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
||||
</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user