Compare commits

...

208 Commits

Author SHA1 Message Date
ArchiBot
9510514fe5 Automatic translations update 2025-12-14 02:35:54 +00:00
Łukasz Domeradzki
b3683d39e3 Bump 2025-12-14 02:29:37 +01:00
Łukasz Domeradzki
23f9f58f6c Use more user-friendly warning 2025-12-14 02:26:34 +01:00
Łukasz Domeradzki
f0dfbc5ee4 Remove --system-required from docker, as there's no dbus there 2025-12-14 02:17:14 +01:00
Łukasz Domeradzki
8ac4efe392 Make --system-required work on Linux (systemd) (#3526)
* Initial POC

* Extract the parts that interest us from auto-generated file

* Add support for no dbus being available

* Add final bits
2025-12-14 01:46:22 +01:00
renovate[bot]
d4691ced51 chore(deps): update asf-ui digest to 9e1d5e3 2025-12-13 09:45:31 +00:00
renovate[bot]
d679bf9307 chore(deps): update asf-ui digest to cd1f819 2025-12-13 02:47:37 +00:00
renovate[bot]
564d0bf9a4 chore(deps): update github artifact actions (#3525)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 22:26:26 +01:00
renovate[bot]
2f848fe585 chore(deps): update dessant/lock-threads action to v6 (#3524)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 22:24:35 +01:00
renovate[bot]
bf34d2e91e chore(deps): update dependency scalar.aspnetcore to 2.11.6 2025-12-12 17:14:56 +00:00
renovate[bot]
83e4c7f63a chore(deps): update asf-ui digest to ab86669 2025-12-12 05:56:06 +00:00
ArchiBot
1e2e52943d Automatic translations update 2025-12-12 02:30:16 +00:00
Łukasz Domeradzki
4a9ecc52c1 Bump 2025-12-11 20:22:46 +01:00
Łukasz Domeradzki
10fc914ac1 Add Winter Sale 2025 to SalesBlacklist 2025-12-11 20:22:25 +01:00
renovate[bot]
7e9c49cc79 chore(deps): update dependency scalar.aspnetcore to 2.11.5 2025-12-11 06:32:14 +00:00
renovate[bot]
ab58886d29 chore(deps): update asf-ui digest to c703223 2025-12-11 02:38:02 +00:00
ArchiBot
a5740a43db Automatic translations update 2025-12-11 02:30:45 +00:00
renovate[bot]
223f2b98cb chore(deps): update dotnet monorepo to 10.0.1 2025-12-10 06:31:16 +00:00
renovate[bot]
69b150c8a0 chore(deps): update dependency scalar.aspnetcore to 2.11.3 2025-12-10 02:52:39 +00:00
ArchiBot
f4ea1d44ac Automatic translations update 2025-12-10 02:29:24 +00:00
renovate[bot]
d02504b914 chore(deps): update dependency scalar.aspnetcore to 2.11.2 2025-12-09 03:35:28 +00:00
ArchiBot
c363af8c3a Automatic translations update 2025-12-09 02:27:11 +00:00
Łukasz Domeradzki
c06a22ec93 Bump 2025-12-08 23:33:24 +01:00
Łukasz Domeradzki
ed19d7e3bf Misc, bump 2025-12-08 23:32:17 +01:00
Łukasz Domeradzki
4eee2e2ac7 Fix authentication flow when reaching max failures in credentials provider
This one is tricky, previously we've properly handled max failures, and told SK2 to abort the request with operation canceled exception, which we even handled back in bot flow, so it looked OK at first, but the bot didn't do anything with that, which resulted in forced TryAnotherCM disconnection after 1 minute of inactivity.

Since we need to be informed what to do in such case, simple cancellation of flow is not enough, we require a custom exception to handle, which will tell us the precise reason for failure + possible count of them, and that will in result allow us to react accordingly in the bot flow, e.g. by stopping the bot if needed.
2025-12-08 23:25:15 +01:00
Łukasz Domeradzki
90fe1a9448 Bump 2025-12-08 21:55:29 +01:00
Łukasz Domeradzki
8c26dcb7c2 Misc 2025-12-08 21:55:24 +01:00
ArchiBot
ba8150b27a Automatic translations update 2025-12-08 02:28:30 +00:00
ArchiBot
612b3dd3ef Automatic translations update 2025-12-06 02:23:51 +00:00
renovate[bot]
a551568f2b chore(deps): update dependency scalar.aspnetcore to 2.11.1 2025-12-04 20:53:14 +00:00
renovate[bot]
31615ef64d chore(deps): update asf-ui digest to 00bfe2e 2025-12-03 13:05:45 +00:00
renovate[bot]
0f0f1bfcd3 chore(deps): update actions/setup-node action to v6.1.0 2025-12-03 08:41:07 +00:00
renovate[bot]
702e27c466 chore(deps): update asf-ui digest to 93e8a77 2025-12-03 04:40:17 +00:00
renovate[bot]
921263674d chore(deps): update actions/checkout action to v6.0.1 2025-12-02 17:32:57 +00:00
renovate[bot]
5110d6d9f9 chore(deps): update crowdin/github-action action to v2.13.0 2025-12-02 10:40:58 +00:00
ArchiBot
5f622128e4 Automatic translations update 2025-11-30 02:33:42 +00:00
ArchiBot
6eee3fb4d9 Automatic translations update 2025-11-29 02:23:49 +00:00
ArchiBot
0aa777734a Automatic translations update 2025-11-28 02:24:18 +00:00
renovate[bot]
be789d706b chore(deps): update wiki digest to afb2ccd 2025-11-27 15:36:14 +00:00
renovate[bot]
03bfc169bb chore(deps): update dependency jetbrains.annotations.sources to 2025.2.4 2025-11-27 03:43:34 +00:00
ArchiBot
12d26bfd60 Automatic translations update 2025-11-27 02:23:56 +00:00
ArchiBot
cb31836c34 Automatic translations update 2025-11-26 02:25:47 +00:00
renovate[bot]
f091707b0d chore(deps): update dependency markdig.signed to 0.44.0 2025-11-25 09:44:27 +00:00
renovate[bot]
f4467fcd38 chore(deps): update actions/setup-dotnet action to v5.0.1 2025-11-25 05:45:11 +00:00
ArchiBot
f00b6bfdf1 Automatic translations update 2025-11-25 02:25:49 +00:00
Łukasz Domeradzki
bbfe0e40c5 Misc 2025-11-24 12:03:28 +01:00
Łukasz Domeradzki
e1e928c4ca Misc
Thanks @xPaw
2025-11-24 11:12:30 +01:00
Pavel Djundik
29cb094430 Optimize generating totp codes (#3512) 2025-11-24 11:11:46 +01:00
Łukasz Domeradzki
dfd2bd9ac4 Add additional OSes to test CI for 2025-11-24 10:42:52 +01:00
ArchiBot
c65ffa44d9 Automatic translations update 2025-11-24 02:30:30 +00:00
Łukasz Domeradzki
cf84c19a1a Bump 2025-11-23 23:48:18 +01:00
renovate[bot]
252e498d8b chore(deps): update asf-ui digest to e2d9422 2025-11-23 05:43:21 +00:00
ArchiBot
1e3a5a5176 Automatic translations update 2025-11-23 02:35:10 +00:00
ArchiBot
c21ca7dbb3 Automatic translations update 2025-11-22 02:22:37 +00:00
renovate[bot]
f7b5699172 chore(deps): update asf-ui digest to 5456569 2025-11-21 18:35:58 +00:00
renovate[bot]
2793775f26 chore(deps): update asf-ui digest to 64ee4fe 2025-11-20 18:29:23 +00:00
renovate[bot]
ab54040d3b chore(deps): update actions/checkout action to v6 (#3509)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-20 19:28:43 +01:00
renovate[bot]
36225c5b93 chore(deps): update dependency humanizer to 3.0.1 2025-11-20 05:06:44 +00:00
renovate[bot]
647dcb5834 chore(deps): update dependency scalar.aspnetcore to 2.11.0 2025-11-19 21:48:11 +00:00
renovate[bot]
12e59a649a chore(deps): update dependency microsoft.identitymodel.jsonwebtokens to 8.15.0 2025-11-19 09:59:04 +00:00
renovate[bot]
f85c36e8ee chore(deps): update actions/checkout action to v5.0.1 2025-11-19 06:02:04 +00:00
ArchiBot
7e4878a3f1 Automatic translations update 2025-11-19 02:24:20 +00:00
renovate[bot]
35aeee1b63 chore(deps): update asf-ui digest to e0c8543 2025-11-18 13:10:03 +00:00
ArchiBot
6f1dffbc01 Automatic translations update 2025-11-18 02:24:16 +00:00
ArchiBot
f6ae839a2f Automatic translations update 2025-11-17 02:26:06 +00:00
renovate[bot]
4d97862ec8 chore(deps): update wiki digest to 8dfa02f 2025-11-16 18:13:49 +00:00
renovate[bot]
84a0b59aba chore(deps): update opentelemetry-dotnet-contrib monorepo to 1.14.0 2025-11-14 05:02:20 +00:00
ArchiBot
1c9a3dbf36 Automatic translations update 2025-11-14 02:24:47 +00:00
renovate[bot]
4540b4a2da chore(deps): update dependency nlog.web.aspnetcore to 6.1.0 2025-11-13 10:02:31 +00:00
renovate[bot]
1e814a63cc chore(deps): update dependency anglesharp to 1.4.0 2025-11-13 08:03:50 +00:00
ArchiBot
f4f70ec802 Automatic translations update 2025-11-13 02:26:29 +00:00
renovate[bot]
41656011a6 chore(deps): update opentelemetry-dotnet monorepo 2025-11-12 18:46:30 +00:00
renovate[bot]
f061be0798 chore(deps): update asf-ui digest to e91078e 2025-11-12 04:50:09 +00:00
ArchiBot
c0a253213d Automatic translations update 2025-11-12 02:24:45 +00:00
Łukasz Domeradzki
67757178c1 Silence yet another warn 2025-11-11 22:42:07 +01:00
Łukasz Domeradzki
03350ce879 Misc 2025-11-11 22:22:06 +01:00
Łukasz Domeradzki
55bc802d59 Misc Rider improvements 2025-11-11 22:13:13 +01:00
Łukasz Domeradzki
a436c053a3 Bump 2025-11-11 20:30:15 +01:00
Łukasz Domeradzki
8547097e78 Closes #3508 2025-11-11 20:24:03 +01:00
Łukasz Domeradzki
a8d9844b01 JsonSerializerDefaults.Strict improvements 2025-11-11 19:50:44 +01:00
Łukasz Domeradzki
867b7270ec Further misc BGR improvements 2025-11-11 19:50:05 +01:00
Łukasz Domeradzki
970998fb4b Rewrite BGR to new OrderedDictionary<T,V> type 2025-11-11 19:27:10 +01:00
Łukasz Domeradzki
1ac4dfd6c8 Bump 2025-11-11 17:22:05 +01:00
Łukasz Domeradzki
ea2bec2f3e Big bump 2025-11-11 17:11:41 +01:00
Łukasz Domeradzki
ee0eef3761 Merge remote-tracking branch 'origin/renovate/mstest-monorepo' 2025-11-11 17:11:15 +01:00
renovate[bot]
fc7ac69fb1 chore(deps): update dotnet monorepo to 10.0.0 2025-11-11 15:38:40 +00:00
renovate[bot]
a32e7639ed chore(deps): update dependency mstest to 4.0.2 2025-11-11 15:38:37 +00:00
Łukasz Domeradzki
c8e8cd27b8 .NET 10 (#3482)
* Initial .NET 10 bump

* Use KnownIPNetworks

* .NET 10 library updates

* First round of trimming fixes

* Fix docker in .NET 10

* Resolve trimming warning

* Bump packages to rc2
2025-11-11 16:37:43 +01:00
renovate[bot]
245daec72e chore(deps): update dependency nlog.web.aspnetcore to 6.0.6 2025-11-09 21:55:39 +00:00
Łukasz Domeradzki
02d18aecf4 Bump 2025-11-09 22:55:23 +01:00
Łukasz Domeradzki
469dee4595 Bump 2025-11-09 22:55:08 +01:00
Łukasz Domeradzki
2e0df5c82b Change the bot when distributing, not keeping missing games and having invalid key 2025-11-09 22:53:47 +01:00
renovate[bot]
677a5503e2 chore(deps): update dependency scalar.aspnetcore to 2.10.3 2025-11-09 01:56:39 +00:00
renovate[bot]
566195129f chore(deps): update dependency anglesharp to 1.3.1 (#3507)
* chore(deps): update dependency anglesharp to 1.3.1

* Resolve new warnings

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Łukasz Domeradzki <JustArchi@JustArchi.net>
2025-11-08 23:46:36 +01:00
Łukasz Domeradzki
b872340c5d Add more debug logging 2025-11-06 21:02:11 +01:00
renovate[bot]
1c4fba6b2e chore(deps): update dependency humanizer to 3.0.0-rc.30 (#3505)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-05 11:59:28 +00:00
renovate[bot]
2adb552618 chore(deps): update asf-ui digest to 184a7a2 2025-11-05 02:01:53 +00:00
renovate[bot]
59e27bc41d chore(deps): update dependency scalar.aspnetcore to 2.10.1 2025-11-04 22:40:01 +00:00
Vita Chumakova
5d1234e2d6 fix: add workaround for .NET 10 SDK breaking change (#3506) 2025-11-04 23:39:12 +01:00
ArchiBot
1f74f9c721 Automatic translations update 2025-11-04 02:23:52 +00:00
renovate[bot]
fb2dcb04ae chore(deps): update dependency scalar.aspnetcore to 2.10.0 2025-11-03 19:43:09 +00:00
ArchiBot
abdaa38389 Automatic translations update 2025-11-03 02:27:14 +00:00
ArchiBot
0830678526 Automatic translations update 2025-11-02 02:27:42 +00:00
renovate[bot]
cb827c7ab5 chore(deps): update wiki digest to 0b57c9c 2025-11-01 21:51:56 +00:00
renovate[bot]
e7ae287f38 chore(deps): update asf-ui digest to 5d50aca 2025-10-31 20:31:26 +00:00
ArchiBot
ffb5322ecb Automatic translations update 2025-10-30 02:24:56 +00:00
renovate[bot]
1ec78cf6a2 chore(deps): update asf-ui digest to 90434c7 2025-10-29 03:58:27 +00:00
ArchiBot
681bd7abcf Automatic translations update 2025-10-28 02:23:31 +00:00
renovate[bot]
1a906aac74 chore(deps): update asf-ui digest to 78842da 2025-10-27 21:37:33 +00:00
ArchiBot
57553fbbb3 Automatic translations update 2025-10-27 02:28:23 +00:00
Łukasz Domeradzki
738d949f1f Misc 2025-10-26 23:15:38 +01:00
Łukasz Domeradzki
b362408704 Bump 2025-10-26 11:28:36 +01:00
Łukasz Domeradzki
32238ba07c Closes #3483 2025-10-26 11:26:48 +01:00
renovate[bot]
2172f8b9eb chore(deps): update asf-ui digest to 3e71e0a 2025-10-24 20:24:29 +00:00
renovate[bot]
609b4914bd chore(deps): update github artifact actions (#3497)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-24 22:23:44 +02:00
Łukasz Domeradzki
e23e507a68 Bump 2025-10-24 21:50:55 +02:00
renovate[bot]
f69ee6364d chore(deps): update asf-ui digest to a46fdc3 2025-10-24 04:45:55 +00:00
renovate[bot]
a468f9301d chore(deps): update opentelemetry-dotnet-contrib monorepo to 1.13.0 2025-10-22 11:11:05 +00:00
renovate[bot]
efa541d68d chore(deps): update dependency markdig.signed to 0.43.0 2025-10-21 11:34:18 +00:00
ArchiBot
068ad1b06a Automatic translations update 2025-10-21 02:23:27 +00:00
renovate[bot]
f3bec05e1f chore(deps): update asf-ui digest to c906498 2025-10-20 18:34:44 +00:00
renovate[bot]
a84dc1b01e chore(deps): update crowdin/github-action action to v2.12.0 2025-10-20 09:46:36 +00:00
renovate[bot]
ca4a3ee972 chore(deps): update dependency scalar.aspnetcore to 2.9.0 2025-10-15 13:53:30 +00:00
Łukasz Domeradzki
1c817426b8 Misc 2025-10-15 13:06:14 +02:00
Łukasz Domeradzki
5ec9bc14a9 Misc 2025-10-15 09:09:46 +02:00
renovate[bot]
67f451069a chore(deps): update dotnet monorepo to 9.0.10 2025-10-15 03:41:02 +00:00
ArchiBot
4eb73af250 Automatic translations update 2025-10-15 02:23:14 +00:00
renovate[bot]
ef60e23a53 chore(deps): update dependency mstest to 4.0.1 2025-10-14 20:09:53 +00:00
renovate[bot]
2b57d0a9e6 chore(deps): update asf-ui digest to 4386078 2025-10-14 14:05:08 +00:00
Łukasz Domeradzki
ae183ae3ad Slightly improve error-reporting related to cross-process semaphore 2025-10-14 13:01:34 +02:00
renovate[bot]
725a3a5106 chore(deps): update actions/setup-node action to v6 (#3494)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-14 12:30:12 +02:00
ArchiBot
289f573b00 Automatic translations update 2025-10-14 02:22:34 +00:00
renovate[bot]
a8a6e658e2 chore(deps): update wiki digest to da954cf 2025-10-13 21:56:40 +00:00
Łukasz Domeradzki
797bb6fc98 Bump 2025-10-11 17:00:21 +02:00
Łukasz Domeradzki
41f61503fb Misc 2025-10-11 16:59:06 +02:00
ArchiBot
764c979560 Automatic translations update 2025-10-11 02:20:05 +00:00
renovate[bot]
a0531ff1f3 chore(deps): update dependency opentelemetry.exporter.prometheus.aspnetcore to 1.13.1-beta.1 2025-10-10 10:40:31 +00:00
renovate[bot]
30d5a4cdc2 chore(deps): update dependency opentelemetry.extensions.hosting to 1.13.1 2025-10-09 20:56:31 +00:00
renovate[bot]
750ff1a09a chore(deps): update dependency nlog.web.aspnetcore to 6.0.5 2025-10-09 14:30:11 +00:00
renovate[bot]
c5cc247e2d chore(deps): update dependency humanizer to 3.0.0-rc.6 2025-10-09 11:32:16 +00:00
renovate[bot]
813bac5e52 chore(deps): update dependency scalar.aspnetcore to 2.8.11 2025-10-08 21:59:49 +00:00
renovate[bot]
267cf1597e chore(deps): update dependency mstest to v4 (#3493)
* chore(deps): update dependency mstest to v4

* Misc improvement

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Łukasz Domeradzki <JustArchi@JustArchi.net>
2025-10-07 22:12:51 +02:00
Łukasz Domeradzki
4716312c3f Handle super rare login failure 2025-10-07 21:35:01 +02:00
renovate[bot]
31b735c3d3 chore(deps): update dependency scalar.aspnetcore to 2.8.10 2025-10-03 01:33:33 +00:00
renovate[bot]
e9baae4d03 chore(deps): update opentelemetry-dotnet monorepo 2025-10-02 06:26:19 +00:00
ArchiBot
f97142200f Automatic translations update 2025-10-02 02:21:12 +00:00
renovate[bot]
34bc25b023 chore(deps): update dependency mstest to 3.11.0 2025-10-01 21:18:07 +00:00
renovate[bot]
ede24b9fd5 chore(deps): update peter-evans/dockerhub-description action to v5 (#3490)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-01 23:17:07 +02:00
ArchiBot
c656b61ce2 Automatic translations update 2025-10-01 02:25:26 +00:00
renovate[bot]
3fb804fbd1 chore(deps): update dependency mstest to 3.10.5 2025-09-30 15:43:59 +00:00
ArchiBot
eb5f126c76 Automatic translations update 2025-09-30 02:21:04 +00:00
renovate[bot]
815d0732c3 chore(deps): update dependency scalar.aspnetcore to 2.8.8 2025-09-29 20:30:19 +00:00
renovate[bot]
a517cf216d chore(deps): update docker/login-action action to v3.6.0 2025-09-29 11:06:26 +00:00
ArchiBot
e5a6eede24 Automatic translations update 2025-09-29 02:22:48 +00:00
ArchiBot
7a3c28f3f6 Automatic translations update 2025-09-28 02:24:01 +00:00
Łukasz Domeradzki
49381cea84 Bump 2025-09-27 14:28:20 +02:00
renovate[bot]
9afa92a22d chore(deps): update dependency scalar.aspnetcore to 2.8.7 2025-09-26 18:39:59 +00:00
ArchiBot
6719903012 Automatic translations update 2025-09-26 02:21:47 +00:00
ArchiBot
2f0047e6c0 Automatic translations update 2025-09-25 02:23:09 +00:00
Łukasz Domeradzki
71a708b515 Misc 2025-09-24 23:22:16 +02:00
Łukasz Domeradzki
50b9011323 Add hashing unit test 2025-09-24 23:17:25 +02:00
renovate[bot]
e4bd4e2371 chore(deps): update wiki digest to 9a11b24 2025-09-24 13:30:51 +00:00
renovate[bot]
f662dc29ed chore(deps): update asf-ui digest to d3b89fc 2025-09-24 04:56:16 +00:00
renovate[bot]
e4ffd5c6ab chore(deps): update dependency scalar.aspnetcore to 2.8.6 2025-09-24 02:34:56 +00:00
ArchiBot
588bc9e691 Automatic translations update 2025-09-24 02:22:26 +00:00
renovate[bot]
3e98887954 chore(deps): update asf-ui digest to 812f732 2025-09-23 11:02:33 +00:00
renovate[bot]
78319f65eb chore(deps): update wiki digest to 4d6696e 2025-09-23 05:12:49 +00:00
Łukasz Domeradzki
c467fd39c1 Add donation section to README 2025-09-23 04:59:56 +02:00
renovate[bot]
896bd82f97 chore(deps): update asf-ui digest to f671af8 2025-09-20 08:24:51 +00:00
renovate[bot]
3a87d7536b chore(deps): update dependency scalar.aspnetcore to 2.8.5 2025-09-19 22:54:28 +00:00
Łukasz Domeradzki
1b245a568f Apply selected .NET 10 improvements 2025-09-19 23:19:24 +02:00
ArchiBot
95eb6b2c63 Automatic translations update 2025-09-19 02:22:16 +00:00
ArchiBot
616d5d2cdb Automatic translations update 2025-09-18 02:20:49 +00:00
renovate[bot]
9e1edc58ab chore(deps): update asf-ui digest to 65a5f0e 2025-09-16 17:57:48 +00:00
renovate[bot]
7df227b584 chore(deps): update dependency scalar.aspnetcore to 2.8.4 2025-09-16 14:30:09 +00:00
ArchiBot
be0f2ab537 Automatic translations update 2025-09-16 02:20:50 +00:00
ArchiBot
885c679033 Automatic translations update 2025-09-15 02:23:39 +00:00
renovate[bot]
0575e714ae chore(deps): update asf-ui digest to 6797c76 2025-09-14 21:07:28 +00:00
renovate[bot]
d1f3074c90 chore(deps): update dependency markdig.signed to 0.42.0 2025-09-14 13:58:14 +00:00
renovate[bot]
3f3a3b161b chore(deps): update dependency scalar.aspnetcore to 2.8.3 2025-09-14 09:42:27 +00:00
renovate[bot]
c5af29ddde chore(deps): update asf-ui digest to 3d70e36 2025-09-14 03:27:08 +00:00
ArchiBot
40dd6100ab Automatic translations update 2025-09-14 02:22:58 +00:00
ArchiBot
42cd1a85d9 Automatic translations update 2025-09-13 02:21:32 +00:00
ArchiBot
c196b46337 Automatic translations update 2025-09-12 02:20:35 +00:00
renovate[bot]
e5e133475b chore(deps): update dependency nlog.web.aspnetcore to 6.0.4 2025-09-11 09:30:41 +00:00
ArchiBot
67d191bbf3 Automatic translations update 2025-09-11 02:22:07 +00:00
renovate[bot]
c9502f8462 chore(deps): update dependency scalar.aspnetcore to 2.8.1 2025-09-10 21:33:08 +00:00
ArchiBot
3dbc3b1c5a Automatic translations update 2025-09-10 02:20:41 +00:00
renovate[bot]
c54928bb64 chore(deps): update dependency scalar.aspnetcore to 2.8.0 2025-09-09 22:34:05 +00:00
renovate[bot]
d40d7f0566 chore(deps): update dotnet monorepo to 9.0.9 2025-09-09 16:38:08 +00:00
renovate[bot]
b73ddab2e2 chore(deps): update dependency scalar.aspnetcore to 2.7.4 2025-09-09 14:34:49 +00:00
Łukasz Domeradzki
069523adcd Misc 2025-09-09 15:37:36 +02:00
renovate[bot]
fc310ee24c chore(deps): update dependency scalar.aspnetcore to 2.7.3 2025-09-09 03:27:57 +00:00
ArchiBot
b53d9a0f6f Automatic translations update 2025-09-09 02:22:25 +00:00
Łukasz Domeradzki
035ff7dfe7 Bump 2025-09-08 23:42:26 +02:00
Łukasz Domeradzki
2bbf197108 Add extra synchronization to IPC state management
Thanks @ezhevita
2025-09-08 23:39:29 +02:00
Łukasz Domeradzki
5d2665207a Handle one more case of Steam being down
Thanks @ezhevita
2025-09-08 23:30:11 +02:00
Łukasz Domeradzki
8618b01800 Fix for edge case of MatchableTypes being empty
Thanks @ezhevita
2025-09-08 23:17:23 +02:00
Łukasz Domeradzki
d59d51ae33 Bump 2025-09-08 22:51:03 +02:00
Łukasz Domeradzki
a313a19cec Add support for machine name 2025-09-08 22:50:23 +02:00
Łukasz Domeradzki
c5f7565ac0 Misc 2025-09-08 03:42:12 +02:00
Łukasz Domeradzki
f52486528b Cache generated swagger.json by default 2025-09-08 03:29:17 +02:00
Łukasz Domeradzki
d17399d98b Misc 2025-09-08 02:42:33 +02:00
Łukasz Domeradzki
1eadaad9bd Fix rp command not working with badge upgrades
Of course volvo had to use different endpoint for that, it'd be too easy otherwise
2025-09-08 02:41:31 +02:00
ArchiBot
22e424a78c Automatic translations update 2025-09-07 02:22:59 +00:00
renovate[bot]
712b57e46b chore(deps): update asf-ui digest to 96606b8 2025-09-06 08:37:05 +00:00
renovate[bot]
bc914f0a09 chore(deps): update asf-ui digest to 64ee49e 2025-09-05 21:29:58 +00:00
renovate[bot]
1da2ccbb1c chore(deps): update asf-ui digest to 4e72d57 2025-09-05 03:11:25 +00:00
132 changed files with 1070 additions and 1625 deletions

View File

@@ -5,7 +5,7 @@ on: [push, pull_request]
env:
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_NOLOGO: true
DOTNET_SDK_VERSION: 9.0
DOTNET_SDK_VERSION: 10.0
permissions: {}
@@ -15,19 +15,19 @@ jobs:
fail-fast: false
matrix:
configuration: [Debug, Release]
os: [macos-latest, ubuntu-latest, windows-latest]
os: [macos-latest, macos-15-intel, ubuntu-latest, ubuntu-24.04-arm, windows-latest, windows-11-arm]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
show-progress: false
submodules: recursive
- name: Setup .NET Core
uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}

View File

@@ -14,13 +14,13 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
show-progress: false
submodules: recursive
- name: Upload latest strings for translation on Crowdin
uses: crowdin/github-action@0749939f635900a2521aa6aac7a3766642b2dc71 # v2.11.0
uses: crowdin/github-action@60debf382ee245b21794321190ad0501db89d8c1 # v2.13.0
with:
crowdin_branch_name: main
config: '.github/crowdin.yml'

View File

@@ -19,7 +19,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
show-progress: false
submodules: recursive

View File

@@ -18,7 +18,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
show-progress: false
submodules: recursive
@@ -27,14 +27,14 @@ jobs:
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Login to ghcr.io
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

View File

@@ -19,7 +19,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
show-progress: false
submodules: recursive
@@ -28,14 +28,14 @@ jobs:
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Login to ghcr.io
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -69,7 +69,7 @@ jobs:
push: true
- name: Update DockerHub repository description
uses: peter-evans/dockerhub-description@432a30c9e07499fd01da9f8a49f0faf9e0ca5b77 # v4.0.2
uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

View File

@@ -19,7 +19,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
show-progress: false
submodules: recursive
@@ -28,14 +28,14 @@ jobs:
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Login to ghcr.io
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Lock inactive threads
uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5.0.1
uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v6.0.0
with:
discussion-inactive-days: 90
issue-inactive-days: 60

View File

@@ -6,7 +6,7 @@ env:
CONFIGURATION: Release
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_NOLOGO: true
DOTNET_SDK_VERSION: 9.0
DOTNET_SDK_VERSION: 10.0
NODE_JS_VERSION: 'lts/*'
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
@@ -19,13 +19,13 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
show-progress: false
submodules: recursive
- name: Setup Node.js with npm
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
check-latest: true
node-version: ${{ env.NODE_JS_VERSION }}
@@ -43,7 +43,7 @@ jobs:
run: npm run-script deploy --no-progress --prefix ASF-ui
- name: Upload ASF-ui
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
compression-level: 1
if-no-files-found: error
@@ -82,12 +82,12 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
show-progress: false
- name: Setup .NET Core
uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
@@ -95,7 +95,7 @@ jobs:
run: dotnet --info
- name: Download previously built ASF-ui
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: ASF-ui
path: ASF-ui/dist
@@ -367,7 +367,7 @@ jobs:
subject-path: out/ASF-${{ matrix.variant }}.zip
- name: Upload ASF-${{ matrix.variant }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
compression-level: 1
if-no-files-found: error
@@ -416,7 +416,7 @@ jobs:
- name: Upload ArchiSteamFarm.OfficialPlugins.Monitoring
if: ${{ matrix.os == 'ubuntu-latest' && matrix.variant == 'generic' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
compression-level: 1
if-no-files-found: error
@@ -436,60 +436,60 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
show-progress: false
- name: Download ASF-generic artifact from ubuntu-latest
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: ubuntu-latest_ASF-generic
path: out
- name: Download ASF-linux-arm artifact from ubuntu-latest
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: ubuntu-latest_ASF-linux-arm
path: out
- name: Download ASF-linux-arm64 artifact from ubuntu-latest
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: ubuntu-latest_ASF-linux-arm64
path: out
- name: Download ASF-linux-x64 artifact from ubuntu-latest
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: ubuntu-latest_ASF-linux-x64
path: out
- name: Download ASF-osx-arm64 artifact from macos-latest
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: macos-latest_ASF-osx-arm64
path: out
- name: Download ASF-osx-x64 artifact from macos-latest
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: macos-latest_ASF-osx-x64
path: out
- name: Download ASF-win-arm64 artifact from windows-latest
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: windows-latest_ASF-win-arm64
path: out
- name: Download ASF-win-x64 artifact from windows-latest
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: windows-latest_ASF-win-x64
path: out
- name: Download ArchiSteamFarm.OfficialPlugins.Monitoring artifact
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: ArchiSteamFarm.OfficialPlugins.Monitoring
path: out
@@ -514,7 +514,7 @@ jobs:
subject-path: out/SHA512SUMS
- name: Upload SHA512SUMS
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
compression-level: 1
if-no-files-found: error
@@ -527,7 +527,7 @@ jobs:
subject-path: out/SHA512SUMS.sign
- name: Upload SHA512SUMS.sign
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
compression-level: 1
if-no-files-found: error

View File

@@ -15,7 +15,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
show-progress: false
submodules: recursive
@@ -31,7 +31,7 @@ jobs:
git reset --hard origin/master
- name: Download latest translations from Crowdin
uses: crowdin/github-action@0749939f635900a2521aa6aac7a3766642b2dc71 # v2.11.0
uses: crowdin/github-action@60debf382ee245b21794321190ad0501db89d8c1 # v2.13.0
with:
upload_sources: false
download_translations: true

2
ASF-ui

Submodule ASF-ui updated: 62ed8b8146...9e1d5e33d4

View File

@@ -5,6 +5,7 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations.Sources" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" IncludeAssets="compile" />
<PackageReference Include="SteamKit2" IncludeAssets="compile" />
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
</ItemGroup>

View File

@@ -5,6 +5,7 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations.Sources" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" IncludeAssets="compile" />
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
</ItemGroup>

View File

@@ -6,6 +6,7 @@
<ItemGroup>
<PackageReference Include="AngleSharp" IncludeAssets="compile" />
<PackageReference Include="JetBrains.Annotations.Sources" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" IncludeAssets="compile" />
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
</ItemGroup>

View File

@@ -5,10 +5,10 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations.Sources" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" IncludeAssets="compile" />
<PackageReference Include="Microsoft.CodeAnalysis.ResxSourceGenerator" PrivateAssets="all" />
<PackageReference Include="SteamKit2" IncludeAssets="compile" />
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />
<PackageReference Include="System.Linq.Async" IncludeAssets="compile" />
</ItemGroup>
<ItemGroup>

View File

@@ -121,7 +121,7 @@ internal static class Commands {
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)).Select(static result => result!)];
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
}

View File

@@ -233,6 +233,7 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
HashSet<EAssetType> acceptedMatchableTypes = Bot.BotConfig.MatchableTypes.Where(AcceptedMatchableTypes.Contains).ToHashSet();
if (acceptedMatchableTypes.Count == 0) {
// Should never happen, since IsEligibleForListing() check above ensured we have at least one matchable type
throw new InvalidOperationException(nameof(acceptedMatchableTypes));
}
@@ -905,9 +906,8 @@ internal sealed class RemoteCommunication : IAsyncDisposable, IDisposable {
HashSet<EAssetType> acceptedMatchableTypes = Bot.BotConfig.MatchableTypes.Where(AcceptedMatchableTypes.Contains).ToHashSet();
if (acceptedMatchableTypes.Count == 0) {
Bot.ArchiLogger.LogNullError(acceptedMatchableTypes);
return;
// Should never happen, since IsEligibleForMatching() check above ensured we have at least one matchable type
throw new InvalidOperationException(nameof(acceptedMatchableTypes));
}
if (!await MatchActivelySemaphore.WaitAsync(0).ConfigureAwait(false)) {

View File

@@ -5,6 +5,7 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations.Sources" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" IncludeAssets="compile" />
<PackageReference Include="Microsoft.CodeAnalysis.ResxSourceGenerator" PrivateAssets="all" />
<PackageReference Include="SteamKit2" IncludeAssets="compile" />
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />

View File

@@ -192,7 +192,7 @@ internal static class Commands {
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)).Select(static result => result!)];
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
}
@@ -289,7 +289,7 @@ internal static class Commands {
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)).Select(static result => result!)];
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
}
@@ -362,7 +362,7 @@ internal static class Commands {
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)).Select(static result => result!)];
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
}

View File

@@ -6,6 +6,7 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations.Sources" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" IncludeAssets="compile" />
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" />

View File

@@ -5,6 +5,7 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations.Sources" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" IncludeAssets="compile" />
<PackageReference Include="Microsoft.CodeAnalysis.ResxSourceGenerator" PrivateAssets="all" />
<PackageReference Include="SteamKit2" IncludeAssets="compile" />
<PackageReference Include="System.Composition.AttributedModel" IncludeAssets="compile" />

View File

@@ -122,7 +122,6 @@
<value>Kunne ikke sende inn data fordi det ikke er gyldig SteamID satt som vi kan klassifisere som bidragsyter. Vurder å sette opp {0} egenskapen.</value>
<comment>{0} will be replaced by the name of the config property (e.g. "SteamOwnerID") that the user is expected to set</comment>
</data>
<data name="SubmissionFailedTooManyRequests" xml:space="preserve">
<value>Innsendingen mislyktes på grunn av for mange forespørsler sendt, vi prøver igjen om lag {0} nå.</value>
<comment>{0} will be replaced by translated TimeSpan string (such as "53 minutes")</comment>

View File

@@ -54,12 +54,28 @@ internal sealed class ArchiCryptoHelper {
[TestMethod]
internal async Task CanEncryptDecryptProtectedDataForCurrentUser() {
// Not supported on other platforms than Windows
if (!OperatingSystem.IsWindows()) {
// Not supported on other platforms than Windows
return;
Assert.Inconclusive($"!{nameof(OperatingSystem.IsWindows)}");
}
await CanEncryptDecrypt(ECryptoMethod.ProtectedDataForCurrentUser).ConfigureAwait(false);
}
[DataRow(EHashingMethod.PlainText, TestPassword)]
[DataRow(EHashingMethod.Pbkdf2, "WlS48GNrs1hAhcNHPfV09TPTLhf03gExb6zpaKiwX5A=")]
[DataRow(EHashingMethod.SCrypt, "9LjhjyugakDQ7Haq/ufyTZDfIGeeWbLcE+/9IeKm8gc=")]
[TestMethod]
internal void CanHash(EHashingMethod hashingMethod, string expectedHash) {
if (!Enum.IsDefined(hashingMethod)) {
throw new InvalidEnumArgumentException(nameof(hashingMethod), (int) hashingMethod, typeof(EHashingMethod));
}
ArgumentException.ThrowIfNullOrEmpty(expectedHash);
string hashed = Hash(hashingMethod, TestPassword);
Assert.AreEqual(expectedHash, hashed);
}
}
#pragma warning restore CA1812 // False positive, the class is used during MSTest

View File

@@ -526,7 +526,7 @@ internal sealed class Bot {
ArgumentNullException.ThrowIfNull(itemsToSend);
Dictionary<(uint RealAppID, ulong ContextID, ulong ClassID), long> realResult = itemsToSend.GroupBy(static asset => (asset.RealAppID, asset.ContextID, asset.ClassID)).ToDictionary(static group => group.Key, static group => group.Sum(static asset => asset.Amount));
Assert.AreEqual(expectedResult.Count, realResult.Count);
Assert.HasCount(expectedResult.Count, realResult);
Assert.IsTrue(expectedResult.All(expectation => realResult.TryGetValue(expectation.Key, out long reality) && (expectation.Value == reality)));
}

View File

@@ -44,7 +44,7 @@ internal sealed class IGitHubPluginUpdates {
private readonly TestContext TestContext;
private CancellationToken CancellationToken => TestContext.CancellationTokenSource.Token;
private CancellationToken CancellationToken => TestContext.CancellationToken;
[UsedImplicitly]
public IGitHubPluginUpdates(TestContext testContext) {

View File

@@ -38,7 +38,7 @@ namespace ArchiSteamFarm.Tests;
internal sealed class SteamChatMessage {
private readonly TestContext TestContext;
private CancellationToken CancellationToken => TestContext.CancellationTokenSource.Token;
private CancellationToken CancellationToken => TestContext.CancellationToken;
[UsedImplicitly]
public SteamChatMessage(TestContext testContext) {

View File

@@ -45,6 +45,7 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTrailingCommaInSinglelineLists/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTypeMemberModifiers/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTypeModifiers/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AsyncVoidEventHandlerMethod/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AsyncVoidMethod/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadAttributeBracketsSpaces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=BadBracesSpaces/@EntryIndexedValue">WARNING</s:String>
@@ -189,6 +190,7 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToLambdaExpressionWhenPossible/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=DuplicatedChainedIfBodies/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=DuplicatedSequentialIfBodies/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=DuplicatedSwitchExpressionArms/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=DuplicatedSwitchSectionBodies/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=DuplicateResource/@EntryIndexedValue">DO_NOT_SHOW</s:String>
@@ -241,6 +243,7 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MissingSpace/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MoveLocalFunctionAfterJumpStatement/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MoveToExistingPositionalDeconstructionPattern/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MoveToExtensionBlock/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MultipleSpaces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MultipleStatementsOnOneLine/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MultipleTypeMembersOnOneLine/@EntryIndexedValue">WARNING</s:String>

View File

@@ -4,6 +4,11 @@
<OutputType>Exe</OutputType>
</PropertyGroup>
<!-- TODO: It seems CA1515 is no longer respected inside editorconfig, might be possible to remove later -->
<PropertyGroup>
<NoWarn>$(NoWarn),CA1515</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AngleSharp" />
<PackageReference Include="CryptSharpStandard" />
@@ -18,8 +23,8 @@
<PackageReference Include="Scalar.AspNetCore" />
<PackageReference Include="SteamKit2" />
<PackageReference Include="System.Composition" />
<PackageReference Include="System.Linq.Async" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" />
<PackageReference Include="Tmds.DBus.Protocol" />
</ItemGroup>
<ItemGroup>

View File

@@ -355,8 +355,8 @@ public static class ASF {
}
ArchiLogger.LogGenericInfo(Strings.IPCConfigChanged);
await ArchiKestrel.Stop().ConfigureAwait(false);
await ArchiKestrel.Start().ConfigureAwait(false);
await ArchiKestrel.Restart().ConfigureAwait(false);
}
private static async Task OnChangedFile(string name, string fullPath) {
@@ -887,10 +887,12 @@ public static class ASF {
MemoryStream memoryStream = new(responseBytes);
await using (memoryStream.ConfigureAwait(false)) {
using ZipArchive zipArchive = new(memoryStream);
ZipArchive zipArchive = new(memoryStream);
if (!await UpdateFromArchive(newVersion, channel.Value, updateOverride, forced, zipArchive).ConfigureAwait(false)) {
ArchiLogger.LogGenericError(Strings.WarningFailed);
await using (zipArchive.ConfigureAwait(false)) {
if (!await UpdateFromArchive(newVersion, channel.Value, updateOverride, forced, zipArchive).ConfigureAwait(false)) {
ArchiLogger.LogGenericError(Strings.WarningFailed);
}
}
}
} catch (Exception e) {

View File

@@ -37,6 +37,8 @@ using System.Threading.Tasks;
using ArchiSteamFarm.Localization;
using ArchiSteamFarm.Storage;
using ArchiSteamFarm.Web;
using Microsoft.Win32.SafeHandles;
using Tmds.DBus.Protocol;
namespace ArchiSteamFarm.Core;
@@ -69,13 +71,20 @@ internal static class OS {
}
}
private static SafeHandle? InhibitLock;
private static Mutex? SingleInstance;
internal static void CoreInit(bool minimized, bool systemRequired) {
internal static async Task CoreInit(bool minimized, bool systemRequired) {
if (minimized) {
MinimizeConsoleWindow();
}
if (OperatingSystem.IsLinux()) {
if (systemRequired) {
await LinuxKeepSystemActive().ConfigureAwait(false);
}
}
if (OperatingSystem.IsWindows()) {
if (systemRequired) {
WindowsKeepSystemActive();
@@ -181,6 +190,12 @@ internal static class OS {
// Instead, we'll dispose the mutex which should automatically release it by the CLR
SingleInstance.Dispose();
SingleInstance = null;
// Release the inhibit lock as well, if needed
if (InhibitLock != null) {
InhibitLock.Dispose();
InhibitLock = null;
}
}
internal static bool VerifyEnvironment() {
@@ -261,6 +276,79 @@ internal static class OS {
NativeMethods.FlashWindowEx(ref flashInfo);
}
[SupportedOSPlatform("Linux")]
private static async Task LinuxKeepSystemActive() {
if (!OperatingSystem.IsLinux()) {
throw new PlatformNotSupportedException();
}
// Docs: https://systemd.io/INHIBITOR_LOCKS
string? systemAddress = Address.System;
if (string.IsNullOrEmpty(systemAddress)) {
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningFailedWithError(nameof(systemAddress)));
return;
}
using Connection connection = new(systemAddress);
try {
await connection.ConnectAsync().ConfigureAwait(false);
} catch (ConnectException e) {
// Possible if no DBus is available at all
ASF.ArchiLogger.LogGenericDebuggingException(e);
ASF.ArchiLogger.LogGenericWarning(Strings.WarningNoSystemRequiredLinuxDependencies);
return;
}
MessageWriter writer = connection.GetMessageWriter();
writer.WriteMethodCallHeader(
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"Inhibit",
"ssss"
);
// Colon-separated list of lock types
writer.WriteString("idle");
// Human-readable, descriptive string of who is taking the lock
writer.WriteString(SharedInfo.PublicIdentifier);
// Human-readable, descriptive string of why the lock is taken
writer.WriteString("--system-required");
// Mode
writer.WriteString("block");
MessageBuffer message = writer.CreateMessage();
try {
// Inhibit() returns a single value, a file descriptor that encapsulates the lock
InhibitLock = await connection.CallMethodAsync(
message, static (response, _) => {
Reader reader = response.GetBodyReader();
return reader.ReadHandle<SafeFileHandle>();
}
).ConfigureAwait(false);
} catch (DBusException e) {
// Possible if login manager does not support inhibit, although that should be super rare
ASF.ArchiLogger.LogGenericDebuggingException(e);
ASF.ArchiLogger.LogGenericWarning(Strings.WarningNoSystemRequiredLinuxDependencies);
return;
}
if (InhibitLock == null) {
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningFailedWithError(nameof(InhibitLock)));
}
}
private static void MinimizeConsoleWindow() {
(_, int top) = Console.GetCursorPosition();

View File

@@ -169,18 +169,6 @@ public static class Utilities {
}
}
[PublicAPI]
public static bool IsClientErrorCode(this HttpStatusCode statusCode) => statusCode is >= HttpStatusCode.BadRequest and < HttpStatusCode.InternalServerError;
[PublicAPI]
public static bool IsRedirectionCode(this HttpStatusCode statusCode) => statusCode is >= HttpStatusCode.Ambiguous and < HttpStatusCode.BadRequest;
[PublicAPI]
public static bool IsServerErrorCode(this HttpStatusCode statusCode) => statusCode is >= HttpStatusCode.InternalServerError and < (HttpStatusCode) 600;
[PublicAPI]
public static bool IsSuccessCode(this HttpStatusCode statusCode) => statusCode is >= HttpStatusCode.OK and < HttpStatusCode.Ambiguous;
[PublicAPI]
public static bool IsValidCdKey(string key) {
ArgumentException.ThrowIfNullOrEmpty(key);
@@ -313,7 +301,7 @@ public static class Utilities {
// Now extract the zip file to entirely new location, this decreases chance of corruptions if user kills the process during this stage
string updateDirectory = Path.Combine(targetDirectory, SharedInfo.UpdateDirectoryNew);
zipArchive.ExtractToDirectory(updateDirectory, true);
await zipArchive.ExtractToDirectoryAsync(updateDirectory, true).ConfigureAwait(false);
// Now, critical section begins, we're going to move all files from target directory to a backup directory
string backupDirectory = Path.Combine(targetDirectory, SharedInfo.UpdateDirectoryOld);
@@ -525,4 +513,20 @@ public static class Utilities {
return prefixes.Any(prefix => !string.IsNullOrEmpty(prefix) && (directory.Length > prefix.Length) && DirectorySeparators.Contains(directory[prefix.Length]) && directory.StartsWith(prefix, StringComparison.Ordinal));
}
#pragma warning disable CA1034 // False positive, there's no other way we can declare this block
extension(HttpStatusCode statusCode) {
[PublicAPI]
public bool IsClientErrorCode() => statusCode is >= HttpStatusCode.BadRequest and < HttpStatusCode.InternalServerError;
[PublicAPI]
public bool IsRedirectionCode() => statusCode is >= HttpStatusCode.Ambiguous and < HttpStatusCode.BadRequest;
[PublicAPI]
public bool IsServerErrorCode() => statusCode is >= HttpStatusCode.InternalServerError and < (HttpStatusCode) 600;
[PublicAPI]
public bool IsSuccessCode() => statusCode is >= HttpStatusCode.OK and < HttpStatusCode.Ambiguous;
}
#pragma warning restore CA1034 // False positive, there's no other way we can declare this block
}

View File

@@ -86,7 +86,11 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
try {
while (true) {
if (!await EnsureFileExists().ConfigureAwait(false)) {
throw new IOException(Strings.FormatWarningFailedWithError(nameof(EnsureFileExists)));
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningFailedWithError(nameof(EnsureFileExists)));
await Task.Delay(SpinLockDelay * 25, cancellationToken).ConfigureAwait(false);
continue;
}
try {
@@ -103,7 +107,9 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
}
} catch (FileNotFoundException) {
throw;
} catch (IOException) {
} catch (IOException e) {
ASF.ArchiLogger.LogGenericDebuggingException(e);
await Task.Delay(SpinLockDelay, cancellationToken).ConfigureAwait(false);
}
}
@@ -128,7 +134,7 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
try {
stopwatch.Stop();
if (stopwatch.ElapsedMilliseconds >= millisecondsTimeout) {
if (stopwatch.ElapsedMilliseconds > millisecondsTimeout) {
return false;
}
@@ -136,7 +142,18 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
while (true) {
if (!await EnsureFileExists().ConfigureAwait(false)) {
throw new IOException(Strings.FormatWarningFailedWithError(nameof(EnsureFileExists)));
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningFailedWithError(nameof(EnsureFileExists)));
if (millisecondsTimeout <= 0) {
return false;
}
int sleep = Math.Min(millisecondsTimeout, SpinLockDelay * 25);
await Task.Delay(sleep, cancellationToken).ConfigureAwait(false);
millisecondsTimeout -= sleep;
continue;
}
try {
@@ -153,13 +170,17 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
}
} catch (FileNotFoundException) {
throw;
} catch (IOException) {
if (millisecondsTimeout <= SpinLockDelay) {
} catch (IOException e) {
ASF.ArchiLogger.LogGenericDebuggingException(e);
if (millisecondsTimeout <= 0) {
return false;
}
await Task.Delay(SpinLockDelay, cancellationToken).ConfigureAwait(false);
millisecondsTimeout -= SpinLockDelay;
int sleep = Math.Min(millisecondsTimeout, SpinLockDelay);
await Task.Delay(sleep, cancellationToken).ConfigureAwait(false);
millisecondsTimeout -= sleep;
}
}
} finally {
@@ -184,20 +205,26 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
}
if (!Directory.Exists(directoryPath)) {
if (OperatingSystem.IsWindows()) {
DirectoryInfo directoryInfo = Directory.CreateDirectory(directoryPath);
try {
if (OperatingSystem.IsWindows()) {
DirectoryInfo directoryInfo = Directory.CreateDirectory(directoryPath);
try {
DirectorySecurity directorySecurity = new(directoryPath, AccessControlSections.All);
try {
DirectorySecurity directorySecurity = new(directoryPath, AccessControlSections.All);
directoryInfo.SetAccessControl(directorySecurity);
} catch (PrivilegeNotHeldException e) {
// Non-critical, user might have no rights to manage the resource
ASF.ArchiLogger.LogGenericDebuggingException(e);
directoryInfo.SetAccessControl(directorySecurity);
} catch (PrivilegeNotHeldException e) {
// Non-critical, user might have no rights to manage the resource
ASF.ArchiLogger.LogGenericDebuggingException(e);
}
} else if (OperatingSystem.IsFreeBSD() || OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) {
// We require global access from all users, as other ASFs might need to put additional files in there
Directory.CreateDirectory(directoryPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute | UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute);
}
} else if (OperatingSystem.IsFreeBSD() || OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) {
// We require global access from all users, as other ASFs might need to put additional files in there
Directory.CreateDirectory(directoryPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute | UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute);
} catch (IOException e) {
ASF.ArchiLogger.LogGenericException(e);
return false;
}
}
@@ -228,11 +255,21 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
await new FileStream(FilePath, fileStreamOptions).DisposeAsync().ConfigureAwait(false);
}
} catch (IOException e) {
// Ignored, if the file was already created in the meantime by another instance, this is fine
ASF.ArchiLogger.LogGenericDebuggingException(e);
if (i == 0) {
// Ignored, if the file was already created in the meantime by another instance, this is fine
ASF.ArchiLogger.LogGenericDebuggingException(e);
continue;
}
// It's not fine if the same issue happened again
ASF.ArchiLogger.LogGenericException(e);
return false;
}
}
return false;
// It's also not fine if we failed to create the file twice in a row
return File.Exists(FilePath);
}
}

View File

@@ -29,7 +29,7 @@ namespace ArchiSteamFarm.Helpers;
[PublicAPI]
public interface ICrossProcessSemaphore {
void Release();
Task WaitAsync(CancellationToken cancellationToken = default);
Task<bool> WaitAsync(int millisecondsTimeout, CancellationToken cancellationToken = default);
public void Release();
public Task WaitAsync(CancellationToken cancellationToken = default);
public Task<bool> WaitAsync(int millisecondsTimeout, CancellationToken cancellationToken = default);
}

View File

@@ -29,6 +29,7 @@ using System.Reflection;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using System.Threading;
using System.Threading.Tasks;
@@ -116,12 +117,15 @@ public static class JsonUtilities {
[UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode", Justification = "We don't care about trimmed assemblies, as we need it to work only with the known (used) ones")]
private static JsonSerializerOptions CreateDefaultJsonSerializerOptions(bool writeIndented = false) =>
new() {
new(JsonSerializerDefaults.Strict) {
AllowTrailingCommas = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
IndentCharacter = '\t',
IndentSize = 1,
PropertyNamingPolicy = null,
ReadCommentHandling = JsonCommentHandling.Skip,
TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { ApplyCustomModifiers } },
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
WriteIndented = writeIndented
};

View File

@@ -30,6 +30,7 @@ using System.Net;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
using ArchiSteamFarm.Core;
using ArchiSteamFarm.Helpers.Json;
@@ -55,7 +56,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using NLog.Web;
using Scalar.AspNetCore;
using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;
using IPNetwork = System.Net.IPNetwork;
namespace ArchiSteamFarm.IPC;
@@ -64,6 +65,8 @@ internal static class ArchiKestrel {
internal static HistoryTarget? HistoryTarget { get; private set; }
private static readonly SemaphoreSlim StateSemaphore = new(1, 1);
private static WebApplication? WebApplication;
internal static void OnNewHistoryTarget(HistoryTarget? historyTarget = null) {
@@ -78,43 +81,43 @@ internal static class ArchiKestrel {
}
}
internal static async Task Start() {
if (WebApplication != null) {
return;
}
ASF.ArchiLogger.LogGenericInfo(Strings.IPCStarting);
// Init history logger for /Api/Log usage
Logging.InitHistoryLogger();
WebApplication webApplication = await CreateWebApplication().ConfigureAwait(false);
internal static async Task Restart() {
await StateSemaphore.WaitAsync().ConfigureAwait(false);
try {
// Start the server
await webApplication.StartAsync().ConfigureAwait(false);
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
await webApplication.DisposeAsync().ConfigureAwait(false);
await StopInternally().ConfigureAwait(false);
await StartInternally().ConfigureAwait(false);
} finally {
StateSemaphore.Release();
}
}
internal static async Task Start() {
if (IsRunning) {
return;
}
WebApplication = webApplication;
await StateSemaphore.WaitAsync().ConfigureAwait(false);
ASF.ArchiLogger.LogGenericInfo(Strings.IPCReady);
try {
await StartInternally().ConfigureAwait(false);
} finally {
StateSemaphore.Release();
}
}
internal static async Task Stop() {
if (WebApplication == null) {
if (!IsRunning) {
return;
}
await WebApplication.StopAsync().ConfigureAwait(false);
await WebApplication.DisposeAsync().ConfigureAwait(false);
await StateSemaphore.WaitAsync().ConfigureAwait(false);
WebApplication = null;
try {
await StopInternally().ConfigureAwait(false);
} finally {
StateSemaphore.Release();
}
}
[UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode", Justification = "PathString is a primitive, it's unlikely to be trimmed to the best of our knowledge")]
@@ -248,6 +251,11 @@ internal static class ArchiKestrel {
// Add support for websockets that we use e.g. in /Api/NLog
app.UseWebSockets();
// Add support for output caching
if (ASF.GlobalConfig?.OptimizationMode != GlobalConfig.EOptimizationMode.MinMemoryUsage) {
app.UseOutputCache();
}
// Add additional endpoints provided by plugins
foreach (IWebServiceProvider plugin in PluginsCore.ActivePlugins.OfType<IWebServiceProvider>()) {
try {
@@ -261,7 +269,11 @@ internal static class ArchiKestrel {
app.MapControllers();
// Add support for OpenAPI, responsible for automatic API documentation generation, this should be on the end, once we're done with API
app.MapOpenApi("/swagger/{documentName}/swagger.json");
IEndpointConventionBuilder openApi = app.MapOpenApi("/swagger/{documentName}/swagger.json");
if (ASF.GlobalConfig?.OptimizationMode != GlobalConfig.EOptimizationMode.MinMemoryUsage) {
openApi.CacheOutput();
}
// Add support for swagger UI, this should be after swagger, obviously
app.MapScalarApiReference(
@@ -311,7 +323,7 @@ internal static class ArchiKestrel {
if (knownNetworks != null) {
foreach (IPNetwork knownNetwork in knownNetworks) {
options.KnownNetworks.Add(knownNetwork);
options.KnownIPNetworks.Add(knownNetwork);
}
}
}
@@ -334,6 +346,11 @@ internal static class ArchiKestrel {
services.AddCors(static options => options.AddDefaultPolicy(static policyBuilder => policyBuilder.AllowAnyOrigin()));
}
// Add support for output caching
if (ASF.GlobalConfig?.OptimizationMode != GlobalConfig.EOptimizationMode.MinMemoryUsage) {
services.AddOutputCache();
}
// Add support for OpenAPI, responsible for automatic API documentation generation
services.AddOpenApi(
SharedInfo.ASF, static options => {
@@ -505,4 +522,43 @@ internal static class ArchiKestrel {
headers.CacheControl = cacheControl;
}
private static async Task StartInternally() {
if (WebApplication != null) {
return;
}
ASF.ArchiLogger.LogGenericInfo(Strings.IPCStarting);
// Init history logger for /Api/Log usage
Logging.InitHistoryLogger();
WebApplication webApplication = await CreateWebApplication().ConfigureAwait(false);
try {
// Start the server
await webApplication.StartAsync().ConfigureAwait(false);
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
await webApplication.DisposeAsync().ConfigureAwait(false);
return;
}
WebApplication = webApplication;
ASF.ArchiLogger.LogGenericInfo(Strings.IPCReady);
}
private static async Task StopInternally() {
if (WebApplication == null) {
return;
}
await WebApplication.StopAsync().ConfigureAwait(false);
await WebApplication.DisposeAsync().ConfigureAwait(false);
WebApplication = null;
}
}

View File

@@ -24,7 +24,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Text.Json;
@@ -227,7 +226,7 @@ public sealed class BotController : ArchiController {
[EndpointSummary("Adds keys to redeem using BGR to given bot")]
[HttpPost("{botNames:required}/GamesToRedeemInBackground")]
[ProducesResponseType<GenericResponse<IReadOnlyDictionary<string, IOrderedDictionary>>>((int) HttpStatusCode.OK)]
[ProducesResponseType<GenericResponse<IReadOnlyDictionary<string, OrderedDictionary<string, string>>>>((int) HttpStatusCode.OK)]
[ProducesResponseType<GenericResponse>((int) HttpStatusCode.BadRequest)]
public async Task<ActionResult<GenericResponse>> GamesToRedeemInBackgroundPost(string botNames, [FromBody] BotGamesToRedeemInBackgroundRequest request) {
ArgumentException.ThrowIfNullOrEmpty(botNames);
@@ -243,21 +242,21 @@ public sealed class BotController : ArchiController {
return BadRequest(new GenericResponse(false, Strings.FormatBotNotFound(botNames)));
}
IOrderedDictionary validGamesToRedeemInBackground = Bot.ValidateGamesToRedeemInBackground(request.GamesToRedeemInBackground);
Bot.FilterGamesToRedeemInBackground(request.GamesToRedeemInBackground);
if (validGamesToRedeemInBackground.Count == 0) {
return BadRequest(new GenericResponse(false, Strings.FormatErrorIsEmpty(nameof(validGamesToRedeemInBackground))));
if (request.GamesToRedeemInBackground.Count == 0) {
return BadRequest(new GenericResponse(false, Strings.FormatErrorIsEmpty(nameof(request.GamesToRedeemInBackground))));
}
await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.AddGamesToRedeemInBackground(validGamesToRedeemInBackground)))).ConfigureAwait(false);
await Utilities.InParallel(bots.Select(bot => Task.Run(() => bot.AddGamesToRedeemInBackground(request.GamesToRedeemInBackground)))).ConfigureAwait(false);
Dictionary<string, IOrderedDictionary> result = new(bots.Count, Bot.BotsComparer);
Dictionary<string, OrderedDictionary<string, string>> result = new(bots.Count, Bot.BotsComparer);
foreach (Bot bot in bots) {
result[bot.BotName] = validGamesToRedeemInBackground;
result[bot.BotName] = request.GamesToRedeemInBackground;
}
return Ok(new GenericResponse<IReadOnlyDictionary<string, IOrderedDictionary>>(result));
return Ok(new GenericResponse<IReadOnlyDictionary<string, OrderedDictionary<string, string>>>(result));
}
[EndpointSummary("Provides input value to given bot for next usage")]

View File

@@ -124,19 +124,19 @@ internal sealed class ApiAuthenticationMiddleware {
return (HttpStatusCode.OK, true);
}
if (ForwardedHeadersOptions.KnownNetworks.Count == 0) {
if (ForwardedHeadersOptions.KnownIPNetworks.Count == 0) {
return (HttpStatusCode.Forbidden, true);
}
if (clientIP.IsIPv4MappedToIPv6) {
IPAddress mappedClientIP = clientIP.MapToIPv4();
if (ForwardedHeadersOptions.KnownNetworks.Any(network => network.Contains(mappedClientIP))) {
if (ForwardedHeadersOptions.KnownIPNetworks.Any(network => network.Contains(mappedClientIP))) {
return (HttpStatusCode.OK, true);
}
}
return (ForwardedHeadersOptions.KnownNetworks.Any(network => network.Contains(clientIP)) ? HttpStatusCode.OK : HttpStatusCode.Forbidden, true);
return (ForwardedHeadersOptions.KnownIPNetworks.Any(network => network.Contains(clientIP)) ? HttpStatusCode.OK : HttpStatusCode.Forbidden, true);
}
if (!context.Request.Headers.TryGetValue(HeadersField, out StringValues passwords) && !context.Request.Query.TryGetValue("password", out passwords)) {

View File

@@ -23,7 +23,7 @@
using System;
using JetBrains.Annotations;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
namespace ArchiSteamFarm.IPC.Integration;

View File

@@ -22,8 +22,9 @@
// limitations under the License.
using System;
using System.Globalization;
using JetBrains.Annotations;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
namespace ArchiSteamFarm.IPC.Integration;
@@ -45,16 +46,16 @@ public sealed class SwaggerItemsMinMaxAttribute : CustomSwaggerAttribute {
public override void Apply(OpenApiSchema schema) {
ArgumentNullException.ThrowIfNull(schema);
if (schema.Items == null) {
if (schema.Items is not OpenApiSchema items) {
throw new InvalidOperationException(nameof(schema.Items));
}
if (BackingMinimum.HasValue) {
schema.Items.Minimum = BackingMinimum.Value;
items.Minimum = BackingMinimum.Value.ToString(CultureInfo.InvariantCulture);
}
if (BackingMaximum.HasValue) {
schema.Items.Maximum = BackingMaximum.Value;
items.Maximum = BackingMaximum.Value.ToString(CultureInfo.InvariantCulture);
}
}
}

View File

@@ -22,10 +22,9 @@
// limitations under the License.
using System;
using System.Text.Json.Nodes;
using JetBrains.Annotations;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
namespace ArchiSteamFarm.IPC.Integration;
@@ -36,10 +35,20 @@ public sealed class SwaggerSecurityCriticalAttribute : CustomSwaggerAttribute {
public override void Apply(OpenApiSchema schema) {
ArgumentNullException.ThrowIfNull(schema);
if (schema.Items is { Reference: null }) {
schema.Items.AddExtension(ExtensionName, new OpenApiBoolean(true));
} else {
schema.AddExtension(ExtensionName, new OpenApiBoolean(true));
JsonValue value = JsonValue.Create(true);
if (schema.Items != null) {
if (schema.Items is OpenApiSchema items) {
items.AddExtension(ExtensionName, new JsonNodeExtension(value));
} else if (schema.Items.Extensions != null) {
schema.Items.Extensions[ExtensionName] = new JsonNodeExtension(value);
} else {
throw new InvalidOperationException(nameof(schema.Items));
}
return;
}
schema.AddExtension(ExtensionName, new JsonNodeExtension(value));
}
}

View File

@@ -22,8 +22,9 @@
// limitations under the License.
using System;
using System.Globalization;
using JetBrains.Annotations;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
using SteamKit2;
namespace ArchiSteamFarm.IPC.Integration;
@@ -38,7 +39,7 @@ public sealed class SwaggerSteamIdentifierAttribute : CustomSwaggerAttribute {
public override void Apply(OpenApiSchema schema) {
ArgumentNullException.ThrowIfNull(schema);
schema.Minimum = new SteamID(MinimumAccountID, Universe, AccountType);
schema.Maximum = new SteamID(MaximumAccountID, Universe, AccountType);
schema.Minimum = new SteamID(MinimumAccountID, Universe, AccountType).ConvertToUInt64().ToString(CultureInfo.InvariantCulture);
schema.Maximum = new SteamID(MaximumAccountID, Universe, AccountType).ConvertToUInt64().ToString(CultureInfo.InvariantCulture);
}
}

View File

@@ -22,36 +22,50 @@
// limitations under the License.
using System;
using System.Linq;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Nodes;
using JetBrains.Annotations;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
namespace ArchiSteamFarm.IPC.Integration;
[PublicAPI]
public sealed class SwaggerValidValuesAttribute : CustomSwaggerAttribute {
private const string ExtensionName = "x-valid-values";
public int[]? ValidIntValues { get; init; }
public string[]? ValidStringValues { get; init; }
[UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode", Justification = "We're not creating json values with non-primitive types")]
public override void Apply(OpenApiSchema schema) {
ArgumentNullException.ThrowIfNull(schema);
OpenApiArray validValues = [];
JsonArray validValues = [];
if (ValidIntValues != null) {
validValues.AddRange(ValidIntValues.Select(static type => new OpenApiInteger(type)));
foreach (int value in ValidIntValues) {
validValues.Add(JsonValue.Create(value));
}
}
if (ValidStringValues != null) {
validValues.AddRange(ValidStringValues.Select(static type => new OpenApiString(type)));
foreach (string value in ValidStringValues) {
validValues.Add(JsonValue.Create(value));
}
}
if (schema.Items is { Reference: null }) {
schema.Items.AddExtension("x-valid-values", validValues);
} else {
schema.AddExtension("x-valid-values", validValues);
if (schema.Items != null) {
if (schema.Items is OpenApiSchema items) {
items.AddExtension(ExtensionName, new JsonNodeExtension(validValues));
} else if (schema.Items.Extensions != null) {
schema.Items.Extensions[ExtensionName] = new JsonNodeExtension(validValues);
} else {
throw new InvalidOperationException(nameof(schema.Items));
}
return;
}
schema.AddExtension(ExtensionName, new JsonNodeExtension(validValues));
}
}

View File

@@ -29,7 +29,7 @@ using ArchiSteamFarm.IPC.Integration;
using ArchiSteamFarm.Storage;
using JetBrains.Annotations;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
namespace ArchiSteamFarm.IPC.OpenApi;
@@ -40,7 +40,6 @@ internal sealed class DocumentTransformer : IOpenApiDocumentTransformer {
ArgumentNullException.ThrowIfNull(document);
ArgumentNullException.ThrowIfNull(context);
document.Info ??= new OpenApiInfo();
document.Info.Title = $"{SharedInfo.AssemblyName} API";
document.Info.Version = SharedInfo.Version.ToString();
@@ -53,7 +52,7 @@ internal sealed class DocumentTransformer : IOpenApiDocumentTransformer {
document.Info.License.Url = new Uri(SharedInfo.LicenseURL);
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes ??= new Dictionary<string, OpenApiSecurityScheme>(1);
document.Components.SecuritySchemes ??= new Dictionary<string, IOpenApiSecurityScheme>(1);
document.Components.SecuritySchemes.Add(
nameof(GlobalConfig.IPCPassword), new OpenApiSecurityScheme {

View File

@@ -28,7 +28,7 @@ using System.Threading.Tasks;
using ArchiSteamFarm.Storage;
using JetBrains.Annotations;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
namespace ArchiSteamFarm.IPC.OpenApi;
@@ -45,13 +45,7 @@ internal sealed class OperationTransformer : IOpenApiOperationTransformer {
operation.Security.Add(
new OpenApiSecurityRequirement {
{
new OpenApiSecurityScheme {
Reference = new OpenApiReference {
Id = nameof(GlobalConfig.IPCPassword),
Type = ReferenceType.SecurityScheme
}
},
new OpenApiSecuritySchemeReference(nameof(GlobalConfig.IPCPassword), context.Document),
[]
}
}

View File

@@ -23,14 +23,13 @@
using System;
using System.Globalization;
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
using ArchiSteamFarm.IPC.Integration;
using JetBrains.Annotations;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
namespace ArchiSteamFarm.IPC.OpenApi;
@@ -72,9 +71,9 @@ internal sealed class SchemaTransformer : IOpenApiSchemaTransformer {
schema.Format = "flags";
}
OpenApiObject definition = new();
JsonObject definition = new();
foreach (object? enumValue in context.JsonTypeInfo.Type.GetEnumValues()) {
foreach (object? enumValue in context.JsonTypeInfo.Type.GetEnumValuesAsUnderlyingType()) {
if (enumValue == null) {
throw new InvalidOperationException(nameof(enumValue));
}
@@ -95,41 +94,26 @@ internal sealed class SchemaTransformer : IOpenApiSchemaTransformer {
continue;
}
IOpenApiAny enumObject;
if (TryCast(enumValue, out int intValue)) {
enumObject = new OpenApiInteger(intValue);
} else if (TryCast(enumValue, out long longValue)) {
enumObject = new OpenApiLong(longValue);
} else if (TryCast(enumValue, out ulong ulongValue)) {
// OpenApi spec doesn't support ulongs as of now
enumObject = new OpenApiString(ulongValue.ToString(CultureInfo.InvariantCulture));
} else {
throw new InvalidOperationException(nameof(enumValue));
}
definition.Add(enumName, enumObject);
// OpenApi seems to support only int and long from underlying enum types: https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/integral-numeric-types
definition[enumName] = enumValue switch {
sbyte value => JsonValue.Create((int) value),
byte value => JsonValue.Create((int) value),
short value => JsonValue.Create((int) value),
ushort value => JsonValue.Create((int) value),
int value => JsonValue.Create(value),
uint value => JsonValue.Create((long) value),
long value => JsonValue.Create(value),
ulong value => JsonValue.Create(value.ToString(CultureInfo.InvariantCulture)),
nint value when nint.Size <= 4 => JsonValue.Create((int) value),
nint value when nint.Size <= 8 => JsonValue.Create((long) value),
nint value => JsonValue.Create(value.ToString(CultureInfo.InvariantCulture)),
nuint value when nuint.Size <= 4 => JsonValue.Create((long) value),
nuint value => JsonValue.Create(value.ToString(CultureInfo.InvariantCulture)),
_ => throw new InvalidOperationException(nameof(enumValue))
};
}
schema.AddExtension("x-definition", definition);
}
private static bool TryCast<T>(object value, out T typedValue) where T : struct {
ArgumentNullException.ThrowIfNull(value);
try {
typedValue = (T) Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);
return true;
} catch (InvalidCastException) {
typedValue = default(T);
return false;
} catch (OverflowException) {
typedValue = default(T);
return false;
}
schema.AddExtension("x-definition", new JsonNodeExtension(definition));
}
}
#pragma warning restore CA1812 // False positive, the class is used internally

View File

@@ -21,7 +21,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Collections.Specialized;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
@@ -33,9 +34,10 @@ namespace ArchiSteamFarm.IPC.Requests;
public sealed class BotGamesToRedeemInBackgroundRequest {
[Description("A string-string map that maps cd-key to redeem (key) to its name (value). Key in the map must be a valid and unique Steam cd-key. Value in the map must be a non-null and non-empty name of the key (e.g. game's name, but can be anything)")]
[JsonInclude]
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
[JsonRequired]
[Required]
public OrderedDictionary GamesToRedeemInBackground { get; private init; } = new();
public OrderedDictionary<string, string> GamesToRedeemInBackground { get; private init; } = new(StringComparer.OrdinalIgnoreCase);
[JsonConstructor]
private BotGamesToRedeemInBackgroundRequest() { }

View File

@@ -75,7 +75,6 @@ public sealed class ASFResponse {
internal ASFResponse(string buildVariant, bool canUpdate, GlobalConfig globalConfig, uint memoryUsage, DateTime processStartTime, Version version) {
ArgumentException.ThrowIfNullOrEmpty(buildVariant);
ArgumentNullException.ThrowIfNull(globalConfig);
ArgumentOutOfRangeException.ThrowIfZero(memoryUsage);
ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(processStartTime, DateTime.UnixEpoch);
ArgumentNullException.ThrowIfNull(version);

View File

@@ -87,7 +87,6 @@ StackTrace:
{2}</value>
<comment>{0} will be replaced by function name, {1} will be replaced by exception message, {2} will be replaced by entire stack trace. Please note that this string should include newlines for formatting.</comment>
</data>
<data name="ErrorFailingRequest" xml:space="preserve">
<value>Памылка запыту да: {0}</value>
<comment>{0} will be replaced by URL of the request</comment>
@@ -186,7 +185,6 @@ StackTrace:
<value>Ваша версія: {0} | Апошняя версія: {1}</value>
<comment>{0} will be replaced by current version, {1} will be replaced by remote version</comment>
</data>
<data name="UserInputSteam2FA" xml:space="preserve">
<value>Калі ласка, увядзіце код 2FA з з мабільнага дадатку Steam: </value>
<comment>Please note that this translation should end with space</comment>
@@ -438,15 +436,6 @@ StackTrace:
<data name="BotStatusLimited" xml:space="preserve">
<value>Бот абмежаваны і не можа атрымліваць карткі праз фарменне.</value>
</data>
<data name="BotAccountFree" xml:space="preserve">
<value>Акаўнт больш не заняты: працэс фармавання адноўлены!</value>
</data>
@@ -456,7 +445,6 @@ StackTrace:
<data name="BotConnecting" xml:space="preserve">
<value>Падключэнне...</value>
</data>
<data name="BotStopping" xml:space="preserve">
<value>Спыненне...</value>
</data>
@@ -464,46 +452,16 @@ StackTrace:
<value>Канфігурацыя вашага бота няправільная. Калі ласка, праверце змест {0} і паспрабуйце яшчэ раз!</value>
<comment>{0} will be replaced by file's path</comment>
</data>
<data name="IdlingGameNotPossible" xml:space="preserve">
<value>Фармаванне {0} ({1}) часова адключана, бо ASF зараз не можа зараз гуляць у гэтую гульню.</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name</comment>
</data>
<data name="BotAccountLocked" xml:space="preserve">
<value>Гэты акаўнт заблакіраваны, працэс фармавання больш недаступны!</value>
</data>
<data name="BotStatusLocked" xml:space="preserve">
<value>Бот абмежаваны і не можа атрымліваць карты падчас фармавання.</value>
</data>
<data name="PluginsWarning" xml:space="preserve">
<value>Вы загрузілі адзін або некалькі карыстальніцкіх убудоў у ASF. Паколькі мы не можам прапанаваць падтрымку мадыфікаваных канфігурацый, калі ласка, звярніцеся да адпаведных распрацоўнікаў, убудовы якіх вы вырашылі выкарыстоўваць у выпадку ўзнікнення якіх-небудзь праблем.</value>
</data>
@@ -519,59 +477,15 @@ StackTrace:
<data name="InteractiveConsoleEnabled" xml:space="preserve">
<value>Інтэрактыўная кансоль цяпер актыўная, націсніце 'c', каб увайсці ў рэжым каманд.</value>
</data>
<data name="BotExtraIdlingCooldown" xml:space="preserve">
<value>Чакаем да {0}, каб быць упэўненымі, што мы можам пачаць фармаванне...</value>
<comment>{0} will be replaced by translated TimeSpan string (such as "1 minute")</comment>
</data>
<data name="Result" xml:space="preserve">
<value>Рэзультат: {0}</value>
<comment>{0} will be replaced by generic result of various functions that use this string</comment>
</data>
<data name="PatchingFiles" xml:space="preserve">
<value>Выпраўленне файлаў ASF...</value>
</data>
</root>

View File

@@ -84,7 +84,6 @@
<value>Изключение: {0}() {1} StackTrace:{2}</value>
<comment>{0} will be replaced by function name, {1} will be replaced by exception message, {2} will be replaced by entire stack trace. Please note that this string should include newlines for formatting.</comment>
</data>
<data name="ErrorFailingRequest" xml:space="preserve">
<value>Провалена заявка: {0}</value>
<comment>{0} will be replaced by URL of the request</comment>
@@ -578,7 +577,6 @@
<value>Ботът има ниво {0}.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ActivelyMatchingItems" xml:space="preserve">
<value>Сравняват се Steam предмети, #{0} път...</value>
<comment>{0} will be replaced by round number</comment>
@@ -678,7 +676,6 @@
<value>Вашият криптиращ ключ е много къс. Препоръчваме да ползвате някой, който е поне {0} байта (символа) голям.</value>
<comment>{0} will be replaced by the number of bytes (characters) recommended</comment>
</data>
<data name="WarningDefaultCryptKeyUsedForEncryption" xml:space="preserve">
<value>Ползвате {0} настройка от {1} стойност, но не сте осигурили персонализиран крипто-ключ. Това напълно нарушава защитата, тъй като ASF е принуден да ползва собствен (познат) ключ. Трябва да осигурите персонализиран крипто-ключ, за да ползвате предлаганата защита от тези настройки.</value>
<comment>{0} will be replaced by the name of a particular setting (e.g. "AES"), {1} will be replaced by the name of the property (e.g. "SteamPassword")</comment>
@@ -698,7 +695,6 @@
<data name="ChecksumMissing" xml:space="preserve">
<value>Отдалечения сървър не знае нищо за версията до която се опитвате да ъпгрейднете. Подобна ситуация е възможна ако версията е публикувана скоро - отказване да се продължи с ъпдейта като допълнителна мярка за сигурност.</value>
</data>
<data name="ChecksumWrong" xml:space="preserve">
<value>Отдалечения сървър отговори с различен checksum, това може да показва корумпирано сваляне или MITM атака - отказване да се продължи с ъпдейта!</value>
</data>
@@ -717,22 +713,4 @@
<value>Опитахте да използвате платена функция {0}, но нямате зададен валиден LicenseID в глобалната конфигурация на ASF. Моля, прегледайте конфигурацията си, тъй като функционалността няма да работи без допълнителни подробности.</value>
<comment>{0} will be replaced by feature name (e.g. MatchActively)</comment>
</data>
</root>

View File

@@ -77,16 +77,10 @@
<value>Podešavanje {0} je netačno: {1}</value>
<comment>{0} will be replaced by name of the configuration property, {1} will be replaced by invalid value</comment>
</data>
<data name="ErrorIsInvalid" xml:space="preserve">
<value>{0} je netačan!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorObjectIsNull" xml:space="preserve">
<value>{0} je null!</value>
<comment>{0} will be replaced by object's name</comment>
@@ -95,13 +89,9 @@
<value>Parsiranje {0} nije uspelo!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorUpdateCheckFailed" xml:space="preserve">
<value>Neuspešno traženje nove verzije!</value>
</data>
<data name="Exiting" xml:space="preserve">
<value>Izlaženje...</value>
</data>
@@ -147,15 +137,9 @@
<data name="UpdateCheckingNewVersion" xml:space="preserve">
<value>Traženje nove verzije...</value>
</data>
<data name="UpdateFinished" xml:space="preserve">
<value>Proces ažuriranja je završen!</value>
</data>
<data name="UserInputSteamLogin" xml:space="preserve">
<value>Molimo Vas unestie vaše Steam korističko ime: </value>
<comment>Please note that this translation should end with space</comment>
@@ -168,7 +152,6 @@
<value>Molimo Vas uneste vašu Steam lozinku: </value>
<comment>Please note that this translation should end with space</comment>
</data>
<data name="IPCReady" xml:space="preserve">
<value>IPC server je spreman!</value>
</data>
@@ -182,48 +165,28 @@
<value>Nije moguće pronaći bilo kakvog bot-a nazvanog {0}!</value>
<comment>{0} will be replaced by bot's name query (string)</comment>
</data>
<data name="CheckingFirstBadgePage" xml:space="preserve">
<value>Proveravanje prve strane bedževa...</value>
</data>
<data name="CheckingOtherBadgePages" xml:space="preserve">
<value>Proveravanje ostalih strana bedževa...</value>
</data>
<data name="Done" xml:space="preserve">
<value>Gotovo!</value>
</data>
<data name="IdlingFinished" xml:space="preserve">
<value>Farmanje završeno!</value>
</data>
<data name="IdlingStopped" xml:space="preserve">
<value>Farmanje zaustavljeno!</value>
</data>
<data name="UnknownCommand" xml:space="preserve">
<value>Nepoznata komanda!</value>
</data>
<data name="BotAcceptingGift" xml:space="preserve">
<value>Prihvatanje poklona: {0}...</value>
<comment>{0} will be replaced by giftID (number)</comment>
</data>
<data name="BotAddLicense" xml:space="preserve">
<value>ID: {0} | Status: {1}</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by status string</comment>
@@ -235,8 +198,6 @@
<data name="BotAlreadyRunning" xml:space="preserve">
<value>Ovaj bot je već pokrenut!</value>
</data>
<data name="BotAuthenticatorToken" xml:space="preserve">
<value>2FA Token: {0}</value>
<comment>{0} will be replaced by generated 2FA token (string)</comment>
@@ -262,8 +223,6 @@
<data name="BotDisconnecting" xml:space="preserve">
<value>Prekidanje veze...</value>
</data>
<data name="BotLoggedOff" xml:space="preserve">
<value>Odjavljen sa Steam-a: {0}</value>
<comment>{0} will be replaced by logging off reason (string)</comment>
@@ -275,28 +234,22 @@
<data name="BotLoggingIn" xml:space="preserve">
<value>Prijavljivanje...</value>
</data>
<data name="BotLootingFailed" xml:space="preserve">
<value>Ponuda za razmjenu nije uspjela!</value>
</data>
<data name="BotLootingSuccess" xml:space="preserve">
<value>Ponuda za razmenu je uspešno poslata!</value>
</data>
<data name="BotSendingTradeToYourself" xml:space="preserve">
<value>Ne možete poslati zahtjev za razmjenu sebi!</value>
</data>
<data name="BotNotConnected" xml:space="preserve">
<value>Ova instanca bot-a nije povezana!</value>
</data>
<data name="BotPointsBalance" xml:space="preserve">
<value>Stanje bodova: {0}</value>
<comment>{0} will be replaced by the points balance value (integer)</comment>
</data>
<data name="BotReconnecting" xml:space="preserve">
<value>Ponovno povezivanje...</value>
</data>
@@ -308,16 +261,12 @@
<value>Ključ: {0} | Status: {1} | Stavke: {2}</value>
<comment>{0} will be replaced by cd-key (string), {1} will be replaced by status string, {2} will be replaced by list of key-value pairs, separated by a comma</comment>
</data>
<data name="BotStatusConnecting" xml:space="preserve">
<value>Bot je povezan sa Steam-om.</value>
</data>
<data name="BotStatusNotRunning" xml:space="preserve">
<value>Bot ne radi.</value>
</data>
<data name="BotStatusPlayingNotAvailable" xml:space="preserve">
<value>Bot se trenutno koristi.</value>
</data>
@@ -329,63 +278,30 @@
<value>{0} je prazan!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="BotConnecting" xml:space="preserve">
<value>Povezivanje...</value>
</data>
<data name="BotStopping" xml:space="preserve">
<value>Zaustavljanje...</value>
</data>
<data name="Initializing" xml:space="preserve">
<value>Učitavanje {0}...</value>
<comment>{0} will be replaced by service name that is being initialized</comment>
</data>
<data name="BotVersion" xml:space="preserve">
<value>{0} V{1}</value>
<comment>{0} will be replaced by program's name (e.g. "ASF"), {1} will be replaced by program's version (e.g. "1.0.0.0"). This string typically has nothing to translate and you should leave it as it is, unless you need to change the format, e.g. in RTL languages.</comment>
</data>
<data name="ErrorAccessDenied" xml:space="preserve">
<value>Pristup odbijеn!</value>
</data>
<data name="BotLevel" xml:space="preserve">
<value>Bot je nivo {0}.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ErrorAborted" xml:space="preserve">
<value>Obustavljeno!</value>
</data>
<data name="PluginLoading" xml:space="preserve">
<value>Učitavanje {0} V{1}...</value>
<comment>{0} will be replaced by the name of the custom ASF plugin, {1} will be replaced by its version</comment>
@@ -393,7 +309,6 @@
<data name="NothingFound" xml:space="preserve">
<value>Ništa nije pronađeno!</value>
</data>
<data name="PleaseWait" xml:space="preserve">
<value>Molimo vas sačekajte...</value>
</data>
@@ -403,55 +318,8 @@
<data name="Executing" xml:space="preserve">
<value>Izvršavanje...</value>
</data>
<data name="Result" xml:space="preserve">
<value>Rezultat: {0}</value>
<comment>{0} will be replaced by generic result of various functions that use this string</comment>
</data>
</root>

View File

@@ -73,19 +73,13 @@
{0}</value>
<comment>{0} will be replaced by content string. Please note that this string should include newline for formatting.</comment>
</data>
<data name="ErrorIsInvalid" xml:space="preserve">
<value>{0} és invàlid!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorNoBotsDefined" xml:space="preserve">
<value>No s'ha definit cap agent. Potser t'ha passat per alt configurar l'ASF? Segueix la guia "posada en marxa" al wiki si tens dificultats.</value>
</data>
<data name="ErrorRequestFailedTooManyTimes" xml:space="preserve">
<value>La petició ha fallat després de {0} intents!</value>
<comment>{0} will be replaced by maximum number of tries</comment>
@@ -93,9 +87,6 @@
<data name="ErrorUpdateCheckFailed" xml:space="preserve">
<value>No s'ha pogut comprovar l'última versió!</value>
</data>
<data name="Exiting" xml:space="preserve">
<value>Sortint...</value>
</data>
@@ -148,11 +139,13 @@
<data name="UpdateFinished" xml:space="preserve">
<value>Procés d'actualització finalitzat!</value>
</data>
<data name="UpdateNewVersionAvailable" xml:space="preserve">
<value>Disponible una nova versió de l'ASF! Sospesa una actualització!</value>
</data>
<data name="UpdateVersionInfo" xml:space="preserve">
<value>Versió local: {0} | Versió remota: {1}</value>
<comment>{0} will be replaced by current version, {1} will be replaced by remote version</comment>
</data>
<data name="UserInputSteamLogin" xml:space="preserve">
<value>Si us plau, introduïu el vostre nom d'usuari de Steam: </value>
<comment>Please note that this translation should end with space</comment>
@@ -165,7 +158,6 @@
<value>Si us plau, introduïu la vostra contrasenya de Steam: </value>
<comment>Please note that this translation should end with space</comment>
</data>
<data name="IPCReady" xml:space="preserve">
<value>Servidor IPC preparat!</value>
</data>
@@ -179,39 +171,67 @@
<value>No s'ha trobat cap bot anomenat {0}!</value>
<comment>{0} will be replaced by bot's name query (string)</comment>
</data>
<data name="CheckingFirstBadgePage" xml:space="preserve">
<value>Comprovant la primera pàgina d'insígnies...</value>
</data>
<data name="CheckingOtherBadgePages" xml:space="preserve">
<value>Comprovant les altres pàgines d'insígnies...</value>
</data>
<data name="ChosenFarmingAlgorithm" xml:space="preserve">
<value>Algorisme de cultiu escollit: {0}</value>
<comment>{0} will be replaced by the name of chosen farming algorithm</comment>
</data>
<data name="Done" xml:space="preserve">
<value>Fet!</value>
</data>
<data name="GamesToIdle" xml:space="preserve">
<value>Hi ha un total de {0} jocs ({1} targetes) restants per cultivar (queden ~{2})...</value>
<comment>{0} will be replaced by number of games, {1} will be replaced by number of cards, {2} will be replaced by translated TimeSpan string (such as "1 day, 5 hours and 30 minutes")</comment>
</data>
<data name="IdlingFinished" xml:space="preserve">
<value>Cultiu finalitzat!</value>
</data>
<data name="IdlingFinishedForGame" xml:space="preserve">
<value>Cultiu finalitzat: {0} ({1}) després de {2} de temps de joc!</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name, {2} will be replaced by translated TimeSpan string (such as "1 day, 5 hours and 30 minutes")</comment>
</data>
<data name="IdlingStatusForGame" xml:space="preserve">
<value>Estat del cultiu per {0} ({1}): Queden {2} targetes</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name, {2} will be replaced by number of cards left to farm</comment>
</data>
<data name="IdlingStopped" xml:space="preserve">
<value>Cultiu aturat!</value>
</data>
<data name="NothingToIdle" xml:space="preserve">
<value>No hi ha res per cultivar en aquest compte!</value>
</data>
<data name="NowIdling" xml:space="preserve">
<value>Cultivant en aquest moment: {0} ({1})</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name</comment>
</data>
<data name="NowIdlingList" xml:space="preserve">
<value>Cultivant en aquest moment: {0}</value>
<comment>{0} will be replaced by list of the games (IDs, numbers), separated by a comma</comment>
</data>
<data name="StillIdling" xml:space="preserve">
<value>Encara cultivant: {0} ({1})</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name</comment>
</data>
<data name="StillIdlingList" xml:space="preserve">
<value>Encara cultivant: {0}</value>
<comment>{0} will be replaced by list of the games (IDs, numbers), separated by a comma</comment>
</data>
<data name="StoppedIdling" xml:space="preserve">
<value>Cultiu aturat: {0} ({1})</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name</comment>
</data>
<data name="StoppedIdlingList" xml:space="preserve">
<value>Cultiu aturat: {0}</value>
<comment>{0} will be replaced by list of the games (IDs, numbers), separated by a comma</comment>
</data>
<data name="UnknownCommand" xml:space="preserve">
<value>Ordre desconeguda!</value>
</data>
<data name="BotAddLicense" xml:space="preserve">
<value>ID: {0} | Estat: {1}</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by status string</comment>
@@ -226,12 +246,18 @@
<data name="BotAuthenticatorConverting" xml:space="preserve">
<value>Convertint arxiu .maFile a format ASF...</value>
</data>
<data name="BotAutomaticIdlingNowPaused" xml:space="preserve">
<value>El cultiu automàtic està en pausa!</value>
</data>
<data name="BotAutomaticIdlingNowResumed" xml:space="preserve">
<value>El cultiu automàtic s'ha reprès!</value>
</data>
<data name="BotAutomaticIdlingPausedAlready" xml:space="preserve">
<value>El cultiu automàtic ja està en pausa!</value>
</data>
<data name="BotAutomaticIdlingResumedAlready" xml:space="preserve">
<value>El cultiu automàtic ja s'ha reprès!</value>
</data>
<data name="BotConnected" xml:space="preserve">
<value>Connectat a Steam!</value>
</data>
@@ -241,158 +267,77 @@
<data name="BotDisconnecting" xml:space="preserve">
<value>Desconnectant...</value>
</data>
<data name="BotLoggingIn" xml:space="preserve">
<value>Iniciant sessió...</value>
</data>
<data name="BotLootingFailed" xml:space="preserve">
<value>L'oferta d'intercanvi ha fallat!</value>
</data>
<data name="BotLootingSuccess" xml:space="preserve">
<value>Oferta d'intercanvi enviada amb èxit!</value>
</data>
<data name="BotSendingTradeToYourself" xml:space="preserve">
<value>No podeu enviar una oferta d'intercanvi a vosaltres mateixos!</value>
</data>
<data name="BotReconnecting" xml:space="preserve">
<value>Tornant a connectar...</value>
</data>
<data name="BotStatusNotRunning" xml:space="preserve">
<value>El bot no està en funcionament.</value>
</data>
<data name="ErrorIsEmpty" xml:space="preserve">
<value>{0} no conté res!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="BotConnecting" xml:space="preserve">
<value>S'està connectant...</value>
</data>
<data name="BotStopping" xml:space="preserve">
<value>Aturant...</value>
</data>
<data name="Initializing" xml:space="preserve">
<value>Inicialitzant {0}...</value>
<comment>{0} will be replaced by service name that is being initialized</comment>
</data>
<data name="TranslationIncomplete" xml:space="preserve">
<value>L'ASF intentarà utilitzar el teu idioma preferit, {0}, però aquesta traducció està completa en un {1}. Potser t'agradaria ajudar a completar o millorar la traducció de l'ASF a la teva llengua?</value>
<comment>{0} will be replaced by culture code, such as "en-US", {1} will be replaced by completeness percentage, such as "78.5%"</comment>
</data>
<data name="BotVersion" xml:space="preserve">
<value>{0} V{1}</value>
<comment>{0} will be replaced by program's name (e.g. "ASF"), {1} will be replaced by program's version (e.g. "1.0.0.0"). This string typically has nothing to translate and you should leave it as it is, unless you need to change the format, e.g. in RTL languages.</comment>
</data>
<data name="ErrorAccessDenied" xml:space="preserve">
<value>Accés denegat!</value>
</data>
<data name="PluginLoaded" xml:space="preserve">
<value>{0} s'ha carregat correctament!</value>
<comment>{0} will be replaced by the name of the custom ASF plugin</comment>
</data>
<data name="PluginLoading" xml:space="preserve">
<value>Inicialitzant {0} V{1}...</value>
<comment>{0} will be replaced by the name of the custom ASF plugin, {1} will be replaced by its version</comment>
</data>
<data name="PleaseWait" xml:space="preserve">
<value>Si us plau, espera...</value>
</data>
<data name="EnterCommand" xml:space="preserve">
<value>Introdueix l'ordre: </value>
</data>
<data name="Executing" xml:space="preserve">
<value>Executant...</value>
</data>
<data name="InteractiveConsoleEnabled" xml:space="preserve">
<value>La consola interactiva ja està activa, prem "c" per entrar al mode d'introducció d'ordres.</value>
</data>
<data name="UpdateCleanup" xml:space="preserve">
<value>Fent neteja dels arxius antics després de l'actualització...</value>
</data>
<data name="Result" xml:space="preserve">
<value>Resultat: {0}</value>
<comment>{0} will be replaced by generic result of various functions that use this string</comment>
</data>
<data name="PatchingFiles" xml:space="preserve">
<value>Apedaçant els arxius de l'ASF...</value>
</data>
</root>

View File

@@ -800,4 +800,7 @@ StackTrace:
<value>Input: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Prohlásili jste --system-required i když na vašem OS chybí požadované závislosti, aby tato funkce fungovala. Zvažte instalaci dbus, i když můžete bezpečně ignorovat toto upozornění, pokud nepotřebujete inhibici pro správné fungování.</value>
</data>
</root>

View File

@@ -800,4 +800,7 @@ Processens oppetid: {1}</value>
<value>Input: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Du har erklæret --system-krævet, selvom dit operativsystem mangler krævede afhængigheder for at denne funktion kan fungere. Overvej at installere dbus, selvom du også trygt kan ignorere denne advarsel, hvis du ikke behøver hæmning for at fungere korrekt.</value>
</data>
</root>

View File

@@ -206,7 +206,7 @@ StackTrace:
<comment>Please note that this translation should end with space</comment>
</data>
<data name="UserInputSteamParentalCode" xml:space="preserve">
<value>Bitte geben Sie Ihre Steam-Familienansicht-PIN ein: </value>
<value>Bitte geben Sie Ihre Steam-Familienansicht (PIN) ein: </value>
<comment>Please note that this translation should end with space</comment>
</data>
<data name="UserInputSteamPassword" xml:space="preserve">
@@ -545,7 +545,7 @@ StackTrace:
<value>Zugriff verweigert!</value>
</data>
<data name="WarningPreReleaseVersion" xml:space="preserve">
<value>Sie verwenden eine Version, die neuer ist als die zuletzt veröffentlichte Version Ihres Aktualisierungskanals. Bitte bedenken Sie, dass Vorabversionen nur für Benutzer gedacht sind, die wissen wie man Fehler meldet, mit Problemen umgeht und Rückmeldung gibt es wird keine technische Unterstützung geben.</value>
<value>Sie verwenden eine Version, die neuer ist als die zuletzt veröffentlichte Version Ihres Aktualisierungskanals. Bitte bedenken Sie, dass Vorabversionen nur an Benutzer gerichtet sind, die bereit sind, Fehlern korrek zu melden, mit Problemen umgehen und Rückmeldungen geben es wird keine technische Unterstützung geben.</value>
</data>
<data name="BotStats" xml:space="preserve">
<value>Aktuelle Speichernutzung: {0} MB.
@@ -801,4 +801,7 @@ Prozesslaufzeit: {1}</value>
<value>Eingabe: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Sie haben --system-required deklariert, obwohl Ihrem Betriebssystem die erforderlichen Abhängigkeiten fehlen, damit diese Funktion funktioniert. Erwägen Sie die Installation von dbus, obwohl Sie diese Warnung auch sicher ignorieren können, wenn Sie keine Hemmung benötigen, um ordnungsgemäß zu funktionieren.</value>
</data>
</root>

View File

@@ -769,8 +769,6 @@ StackTrace:
<value>Βρέθηκε ενημέρωση του πρόσθετου {0} από την έκδοση {1} σε {2}...</value>
<comment>{0} will be replaced by plugin name (string), {1} will be replaced by current plugin's version, {2} will be replaced by remote plugin's version.</comment>
</data>
<data name="PluginUpdateInProgress" xml:space="preserve">
<value>Ενημέρωση του πρόσθετου {0}...</value>
<comment>{0} will be replaced by plugin name (string).</comment>
@@ -794,4 +792,7 @@ StackTrace:
<value>Input: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Έχετε δηλώσει το -- system-required αν και λείπουν οι απαιτούμενες εξαρτήσεις του λειτουργικού σας συστήματος για να λειτουργήσει αυτή η λειτουργία. Σκεφτείτε την εγκατάσταση dbus, αν και μπορείτε επίσης να αγνοήσετε με ασφάλεια αυτή την προειδοποίηση αν δεν χρειάζεστε αναστολή για να λειτουργήσει σωστά.</value>
</data>
</root>

View File

@@ -799,4 +799,7 @@ Tiempo de actividad del proceso: {1}</value>
<value>Entrada: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Ha declarado --system-required, aunque su sistema operativo carece de dependencias requeridas para que esa característica funcione. Considere instalar dbus, aunque también puede ignorar de forma segura esta advertencia si no requiere inhibición para funcionar correctamente.</value>
</data>
</root>

View File

@@ -510,24 +510,6 @@ StackTrace:
<data name="Welcome" xml:space="preserve">
<value>بنظر می رسد اولین استفاده ی شما از این برنامه باشد، خوش آمدید! 3:</value>
</data>
<data name="BotWalletBalance" xml:space="preserve">
<value>موجودی والت: {0} {1}</value>
<comment>{0} will be replaced by wallet balance value, {1} will be replaced by currency name</comment>
@@ -539,19 +521,12 @@ StackTrace:
<value>بات لول {0} است.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ErrorAborted" xml:space="preserve">
<value>کنسل شد!</value>
</data>
<data name="NothingFound" xml:space="preserve">
<value>چیزی پیدا نشد!</value>
</data>
<data name="PleaseWait" xml:space="preserve">
<value>لطفا صبر کنید...</value>
</data>
@@ -561,65 +536,22 @@ StackTrace:
<data name="Executing" xml:space="preserve">
<value>در حال اجرا...</value>
</data>
<data name="UpdateCleanup" xml:space="preserve">
<value>درحال پاک سازی فایل های قدیمی بعد از به روزرسانی...</value>
</data>
<data name="Result" xml:space="preserve">
<value>نتایج: {0}</value>
<comment>{0} will be replaced by generic result of various functions that use this string</comment>
</data>
<data name="PatchingFiles" xml:space="preserve">
<value>در حال پچ کردن فایل های ASF...</value>
</data>
<data name="ErrorIPNotBanned" xml:space="preserve">
<value>آدرس آیپی {0} بن نشده است!</value>
<comment>{0} will be replaced by an IP address which was requested to be unbanned from using IPC</comment>
</data>
<data name="WarningSkipping" xml:space="preserve">
<value>در حال رد کردن: {0}...</value>
<comment>{0} will be replaced by text value (string) of entry being skipped.</comment>
</data>
</root>

View File

@@ -800,4 +800,7 @@ Prosessin käyttöaika: {1}</value>
<value>Syöte: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Olet julistanut --system-pakolliseksi, vaikka käyttöjärjestelmästäsi puuttuu vaaditut riippuvuudet, jotta toiminto toimisi. Harkitse dbusin asentamista, vaikka voit myös turvallisesti ohittaa tämän varoituksen, jos et vaadi estoa toimimaan kunnolla.</value>
</data>
</root>

View File

@@ -800,4 +800,7 @@ Durée de fonctionnement : {1}</value>
<value>Saisie : {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Vous avez déclaré que --system-needed était nécessaire pour que cette fonctionnalité fonctionne, mais il manque à votre système d'exploitation des dépendances nécessaires. Pensez à installer dbus, bien que vous puissiez également ignorer cet avertissement en toute sécurité si vous n'avez pas besoin d'une inhibition pour fonctionner correctement.</value>
</data>
</root>

View File

@@ -87,7 +87,6 @@ StackTrace:
{2}</value>
<comment>{0} will be replaced by function name, {1} will be replaced by exception message, {2} will be replaced by entire stack trace. Please note that this string should include newlines for formatting.</comment>
</data>
<data name="ErrorFailingRequest" xml:space="preserve">
<value>בקשה נכשלה: {0}</value>
<comment>{0} will be replaced by URL of the request</comment>
@@ -581,7 +580,6 @@ StackTrace:
<value>לבוט יש רמה {0}.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ActivelyMatchingItems" xml:space="preserve">
<value>מתאים פריטי Steam, שלב #{0}...</value>
<comment>{0} will be replaced by round number</comment>
@@ -681,7 +679,6 @@ StackTrace:
<value>מפתח ההצפנה שלך קצר מדי. אנו ממליצים להשתמש באחד שאורכו לפחות {0} בייטים (תווים).</value>
<comment>{0} will be replaced by the number of bytes (characters) recommended</comment>
</data>
<data name="WarningDefaultCryptKeyUsedForEncryption" xml:space="preserve">
<value>אתה משתמש בהגדרה {0} של המאפיין {1}, אך לא סיפקת --cryptkey מותאם אישית. זה מביס לחלוטין את ההגנה, מכיוון ש-ASF נאלץ להשתמש במפתח (ידוע) משלו. עליך לספק --cryptkey מותאם אישית כדי לעשות שימוש בהטבת האבטחה שמציעה הגדרה זו.</value>
<comment>{0} will be replaced by the name of a particular setting (e.g. "AES"), {1} will be replaced by the name of the property (e.g. "SteamPassword")</comment>
@@ -701,7 +698,6 @@ StackTrace:
<data name="ChecksumMissing" xml:space="preserve">
<value>השרת המרוחק לא יודע כלום על המהדורה שאליה אנחנו מעדכנים. מצב זה אפשרי אם המהדורה פורסמה לאחרונה - מסרב להמשיך בהליך העדכון באופן מיידי כאמצעי אבטחה נוסף.</value>
</data>
<data name="ChecksumWrong" xml:space="preserve">
<value>שרת מרוחק השיב עם סכום ביקורת אחר, זה עשוי להצביע על הורדה פגומה או התקפת MITM, מסרב להמשיך בהליך העדכון!</value>
</data>
@@ -720,22 +716,4 @@ StackTrace:
<value>ניסית להשתמש בתכונה בתשלום {0} אך אין לך מזהה רישיון חוקי שהוגדר בתצורה הגלובלית של ASF. אנא בדוק את התצורה שלך, מכיוון שהפונקציונליות לא תעבוד ללא פרטים נוספים.</value>
<comment>{0} will be replaced by feature name (e.g. MatchActively)</comment>
</data>
</root>

View File

@@ -181,180 +181,4 @@ Automatsko ažuriranje na tu verziju nije moguće.</value>
<value/>
<comment>{0} will be replaced by version string, {1} will be replaced by update size (in megabytes)</comment>
</data>
</root>

View File

@@ -582,7 +582,6 @@ Ennyi ideje fut: {1}</value>
<value>A bot szintje: {0}.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ActivelyMatchingItems" xml:space="preserve">
<value>Steam tárgyak egyeztetése #{0}...</value>
<comment>{0} will be replaced by round number</comment>
@@ -705,7 +704,6 @@ Ennyi ideje fut: {1}</value>
<data name="ChecksumMissing" xml:space="preserve">
<value>A távoli szerver semmit sem tud a verzióról, amelyre frissítünk. Ez a helyzet akkor lehetséges, ha a verzió a közelmúltban jelent meg további biztonsági intézkedésként nem hajlandó azonnal folytatni a frissítési eljárást.</value>
</data>
<data name="ChecksumWrong" xml:space="preserve">
<value>A távoli szerver más ellenőrzőösszeggel válaszolt, ez hibás letöltésre vagy MITM-támadásra utalhat, és nem hajlandó folytatni a frissítési eljárást!</value>
</data>
@@ -735,19 +733,4 @@ Ennyi ideje fut: {1}</value>
<data name="ErrorTooManyCrashes" xml:space="preserve">
<value>Az ASF-ed túl sokszor crashelt a közelmúltban, és emiatt a folyamat inicializálás ki lett kapcsolva. Vagy nyomozd ki, vagy javítsd meg a felszerelésedet, aztán töröld az ASF.crash fájlod a beállítás könyvtáradból, vagy lásd el --ignorál a nem támogatott felszerelést ha tudod mit csinálsz.</value>
</data>
</root>

View File

@@ -580,7 +580,6 @@
<value>Bot mempunyai level {0}.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ActivelyMatchingItems" xml:space="preserve">
<value>Mencocokkan item dari Steam, fase #{0}...</value>
<comment>{0} will be replaced by round number</comment>
@@ -789,5 +788,4 @@
<data name="CustomPluginUpdatesEnabled" xml:space="preserve">
<value>Plugin kustom telah didaftarkan untuk pembaruan otomatis. Tim ASF ingin mengingatkan Anda bahwa, demi keamanan Anda, Anda hanya boleh mengaktifkan pembaruan otomatis dari pihak yang tepercaya. Jika Anda tidak bermaksud melakukan ini, Anda dapat menonaktifkan pembaruan plugin di konfigurasi global ASF.</value>
</data>
</root>

View File

@@ -798,4 +798,7 @@ Tempo di attività: {1}</value>
<value>Inserisci: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Hai dichiarato --system-requireed, anche se il tuo sistema operativo manca di dipendenze richieste per far funzionare quella funzione. Considerare l'installazione di dbus, anche se si può tranquillamente ignorare questo avviso se non si richiede inibizione per funzionare correttamente.</value>
</data>
</root>

View File

@@ -797,4 +797,7 @@ Process uptime: {1}</value>
<value>入力: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>--system-requiredと宣言しましたが、その機能を動作させるために必要な依存関係が不足しています。 正常に動作するように阻害を必要としない場合は、この警告を無視することもできますが、dbusをインストールすることを検討してください。</value>
</data>
</root>

View File

@@ -68,229 +68,30 @@
<value>ASF ავტომატურად შემოწმედბა ახალ ვერსიისთვის ყველა {0}-ში.</value>
<comment>{0} will be replaced by translated TimeSpan string (such as "24 hours")</comment>
</data>
<data name="Exiting" xml:space="preserve">
<value>გამოსვლა...</value>
</data>
<data name="WarningFailed" xml:space="preserve">
<value>ვერ მოხერხდა!</value>
</data>
<data name="Restarting" xml:space="preserve">
<value>რესტარტდება...</value>
</data>
<data name="Success" xml:space="preserve">
<value>წარმატება!</value>
</data>
<data name="PleaseWait" xml:space="preserve">
<value>გთხოვთ დაელოდოთ...</value>
</data>
<data name="EnterCommand" xml:space="preserve">
<value>შეიყვანეთ ბრძანება: </value>
</data>
<data name="Result" xml:space="preserve">
<value>შედეგი: {0}</value>
<comment>{0} will be replaced by generic result of various functions that use this string</comment>
</data>
<data name="WarningSkipping" xml:space="preserve">
<value>გამოტოვება: {0}...</value>
<comment>{0} will be replaced by text value (string) of entry being skipped.</comment>
</data>
</root>

View File

@@ -584,7 +584,6 @@ StackTrace:
<value>봇은 레벨 {0} 입니다.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ActivelyMatchingItems" xml:space="preserve">
<value>#{0} 번째 Steam 아이템 매칭 중입니다.</value>
<comment>{0} will be replaced by round number</comment>
@@ -684,7 +683,6 @@ StackTrace:
<value>암호키가 너무 짧습니다. 최소한 {0} 바이트(글자수) 길이 이상의 암호키를 사용하는 것을 추천합니다.</value>
<comment>{0} will be replaced by the number of bytes (characters) recommended</comment>
</data>
<data name="WarningDefaultCryptKeyUsedForEncryption" xml:space="preserve">
<value>{1} 속성의 {0} 설정을 사용하고 있습니다만, 별도의 -cryptkey를 사용하고 있지 않습니다. ASF는 자체 (이미 알려진) 키를 사용해야하므로 보호 기능이 제대로 동작하지 않습니다. 설정이 제공하는 보안의 효과를 누리기 위하여 별도의 -cryptkey를 사용해야 합니다.</value>
<comment>{0} will be replaced by the name of a particular setting (e.g. "AES"), {1} will be replaced by the name of the property (e.g. "SteamPassword")</comment>
@@ -704,7 +702,6 @@ StackTrace:
<data name="ChecksumMissing" xml:space="preserve">
<value>원격 서버는 최신 배포본의 업데이트에 대하여 알지 못합니다. 이 상황은 최근에 새로운 배포본이 배포되었을 때 발생할 수 있으며 추가 보안 조치로 업데이트를 즉시 진행하지 않습니다.</value>
</data>
<data name="ChecksumWrong" xml:space="preserve">
<value>원격서버와 체크섬이 다릅니다. 다운로드 받은 실행화일이 깨졌거나, 중간자 공격(MITM) 을 받았을 수도 있습니다. 업데이트를 진행하지 않습니다.</value>
</data>
@@ -738,20 +735,7 @@ StackTrace:
<value>{0} ({1}) 게임이 비공개로 설정되어 있기 때문에 농사를 지을 수 없습니다. ASF로 이 게임 농사를 지으려면 공개로 변경해주세요.</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name</comment>
</data>
<data name="CustomPluginUpdatesEnabled" xml:space="preserve">
<value>커스텀 플러그인들이 자동 업데이트에 등록되었습니다. ASF 팀은 안전을 위해 신뢰할 수 있는 출처들에서만 자동 업데이트를 활성화할 것을 명시 드립니다. 만약 원치 않으신다면, ASF 글로벌 설정에서 플러그인 업데이트를 비활성화할 수 있습니다.</value>
</data>
</root>

View File

@@ -87,7 +87,6 @@ StackTrace:
{2}</value>
<comment>{0} will be replaced by function name, {1} will be replaced by exception message, {2} will be replaced by entire stack trace. Please note that this string should include newlines for formatting.</comment>
</data>
<data name="ErrorFailingRequest" xml:space="preserve">
<value>Užklausa nutrūksta: {0}</value>
<comment>{0} will be replaced by URL of the request</comment>
@@ -581,7 +580,6 @@ Proceso veikimo laikas: {1}</value>
<value>Botas neturi {0} lygio.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ActivelyMatchingItems" xml:space="preserve">
<value>Derinami Steam item'ai, #{0} raundas...</value>
<comment>{0} will be replaced by round number</comment>
@@ -681,7 +679,6 @@ Proceso veikimo laikas: {1}</value>
<value>Jūsų šifravimo raktas yra per trumpas. Rekomenduojame naudoti raktą, kuris yra bent {0} baitų (simbolių) ilgio.</value>
<comment>{0} will be replaced by the number of bytes (characters) recommended</comment>
</data>
<data name="WarningDefaultCryptKeyUsedForEncryption" xml:space="preserve">
<value>Jūs naudojate {0} nustatymą is {1} ypatybės, tačiau nenurodėte tinkintos --cryptkey savybės. Tai prieštarauja apsaugai, kadangi ASF bus priversta naudoti savo (žinomą) raktą. Reiktų nurodyti tinkintą --cryptkey savybę, kad šio gautumėte šio nustatymo naudą.</value>
<comment>{0} will be replaced by the name of a particular setting (e.g. "AES"), {1} will be replaced by the name of the property (e.g. "SteamPassword")</comment>
@@ -701,7 +698,6 @@ Proceso veikimo laikas: {1}</value>
<data name="ChecksumMissing" xml:space="preserve">
<value>Nuotolinis serveris nežino apie išleidimą, į kurį bandote atsinaujinti. Ši situacija galima, jeigu išleidimas buvo neseniai paskelbtas - neleidžiama atnaujinti iš karto dėl papildomos apsaugos.</value>
</data>
<data name="ChecksumWrong" xml:space="preserve">
<value>Nuotolinis serveris atsakė su nesutampančia kontroline suma. Tai gali būti dėl sugadinto atsisiuntimo arba MITM atakos. Atsisakoma tęsti atnaujinimo procesą!</value>
</data>
@@ -720,22 +716,4 @@ Proceso veikimo laikas: {1}</value>
<value>Jūs bandote naudoti mokamą funkciją {0}, tačiau jūs neturite tinkamo LicenseID nustatyto globalioje konfigūracijoje. Prašome patikrinti savo konfigūraciją, kadangi funkcija neveiks be papildomų detalių.</value>
<comment>{0} will be replaced by feature name (e.g. MatchActively)</comment>
</data>
</root>

View File

@@ -799,4 +799,7 @@ Proces uptime: {1}</value>
<value>Input: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Je hebt verklaard --system-verplicht te zijn, hoewel je OS vereiste afhankelijkheden mist om die functie te laten werken. Overweeg het installeren van dbus, maar je kunt deze waarschuwing ook negeren als je geen remmen nodig hebt om goed te werken.</value>
</data>
</root>

View File

@@ -230,7 +230,6 @@ StackTrace:
<value>Kunne ikke finne noen bot som heter {0}!</value>
<comment>{0} will be replaced by bot's name query (string)</comment>
</data>
<data name="BotStatusIdling" xml:space="preserve">
<value>Bot dyrkingsspill: {0} ({1}, {2} kort dråper igjen) fra totalt {3} spill ({4} kort) igjen til gården (~{5} igjen).</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name, {2} will be replaced by number of cards left to farm, {3} will be replaced by total number of games to farm, {4} will be replaced by total number of cards to farm, {5} will be replaced by translated TimeSpan string (such as "1 day, 5 hours and 30 minutes")</comment>
@@ -284,7 +283,6 @@ StackTrace:
<value>Nærliggende nå: {0} ({1})</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name</comment>
</data>
<data name="PlayingNotAvailable" xml:space="preserve">
<value>Å spille er utilgjengelig for øyeblikket, vi vil prøve igjen senere!</value>
</data>
@@ -421,8 +419,6 @@ StackTrace:
<data name="BotReconnecting" xml:space="preserve">
<value>Kobler til på nytt...</value>
</data>
<data name="BotRemovedExpiredLoginKey" xml:space="preserve">
<value>Fjernet utgått innloggingsnøkkel!</value>
</data>
@@ -568,12 +564,10 @@ prosess oppgang: {1}</value>
<data name="BotHasNoWallet" xml:space="preserve">
<value>Bot har ingen lommebok.</value>
</data>
<data name="BotInventory" xml:space="preserve">
<value>{0}/{1} ({2}/{3}): {4} ressurser</value>
<comment>{0} will be replaced by appID (number), {1} will be replaced by contextID (number), {2} will be replaced by app's name (string), {3} will be replaced by name of the context (string), {4} will be replaced by number of assets in the specified inventory (number).</comment>
</data>
<data name="DoneActivelyMatchingItems" xml:space="preserve">
<value>Samsvarer med Steam-elementer, fra omkring #{0}.</value>
<comment>{0} will be replaced by round number</comment>
@@ -585,7 +579,6 @@ prosess oppgang: {1}</value>
<value>Du har flere personlige bot kontoer enn vår øvre anbefalte grense ({0}). Vær oppmerksom på at dette oppsettet ikke støttes og kan forårsake forskjellige Steam-relaterte problemer, inkludert kontosuspensjoner. Sjekk ut FAQ for mer detaljer.</value>
<comment>{0} will be replaced by our maximum recommended bots count (number)</comment>
</data>
<data name="PluginLoading" xml:space="preserve">
<value>Laster {0} V{1}...</value>
<comment>{0} will be replaced by the name of the custom ASF plugin, {1} will be replaced by its version</comment>
@@ -779,4 +772,7 @@ prosess oppgang: {1}</value>
<value>Input: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Du har erklært --system-nødvendig, selv om OS mangler nødvendige avhengigheter for at den funksjonen skal fungere. Vurder å installere dbus, selv om du også trygt kan overse denne advarselen hvis du ikke trenger hemming av denne funksjonen.</value>
</data>
</root>

View File

@@ -800,4 +800,7 @@ Czas procesu: {1}</value>
<value>Wejście: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Zgłosiłeś --system-wymagane, chociaż w systemie operacyjnym brakuje wymaganych zależności, aby ta funkcja działała. Rozważ zainstalowanie dbus, chociaż możesz również bezpiecznie zignorować to ostrzeżenie, jeśli nie wymagasz zahamowania prawidłowego działania.</value>
</data>
</root>

View File

@@ -800,4 +800,7 @@ Tempo de execução: {1}</value>
<value>Entrada: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Você declarou --system-required embora esteja faltando as dependências necessárias para que esse recurso funcione. Considere instalar o dbus, embora você também possa ignorar com segurança este aviso se não exigir inibição para funcionar corretamente.</value>
</data>
</root>

View File

@@ -800,4 +800,7 @@ Tempo de execução: {1}</value>
<value>Input: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Você declarou --system-required embora esteja faltando as dependências necessárias para que esse recurso funcione. Considere instalar o dbus, embora você também possa ignorar com segurança este aviso se não exigir inibição para funcionar corretamente.</value>
</data>
</root>

View File

@@ -800,4 +800,7 @@ Process uptime: {1}</value>
<value>Input: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>You've declared --system-required, although your OS is missing required dependencies for that feature to work. Consider installing dbus, although you can also safely ignore this warning if you do not require inhibition to work properly.</value>
</data>
</root>

View File

@@ -800,4 +800,7 @@ Proces: {1}</value>
<value>Intrare: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Ați declarat --necesar sistemului, deși sistemul dvs. de operare lipsește dependențele necesare pentru ca această caracteristică să funcționeze. Luați în considerare instalarea autobuzului, deși puteți ignora în siguranță această avertizare dacă nu aveți nevoie de inhibiție pentru a funcționa corect.</value>
</data>
</root>

View File

@@ -804,4 +804,7 @@
Файл: Strings.resx</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Вы объявили --system-required, хотя ваша ОС не имеет необходимых зависимостей для работы этой функции. Рассмотрим установку dbus, хотя вы также можете безопасно проигнорировать это предупреждение, если вам не требуется запрещение для нормальной работы.</value>
</data>
</root>

View File

@@ -584,7 +584,6 @@ Doba prevádzky procesu: {1}</value>
<value>Bot má level {0}.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ActivelyMatchingItems" xml:space="preserve">
<value>Porovnávanie položiek na Steame, kolo #{0}...</value>
<comment>{0} will be replaced by round number</comment>
@@ -685,7 +684,6 @@ Interaktívna konzola je teraz aktívna, napíšte "c" pre vstup do príkazovéh
<value>Váš šifrovací kľuč je príliš krátky. Doporučujeme použiť ten, ktorý je aspoň {0} bajtu (znakov) dlhý.</value>
<comment>{0} will be replaced by the number of bytes (characters) recommended</comment>
</data>
<data name="WarningDefaultCryptKeyUsedForEncryption" xml:space="preserve">
<value>Používate {0} nastavenie vlastnosti {1}, ale neposkytujete vlastný --cryptkey. To celkovo ruší ochranu, pretože ASF je nútený použiť svoj vlastný (známy) kľuč. Pre využitie bezpečnostného prínosu ponúkaného týmto nastavením, by ste mali poskytnúť vlastní --cryptkey.</value>
<comment>{0} will be replaced by the name of a particular setting (e.g. "AES"), {1} will be replaced by the name of the property (e.g. "SteamPassword")</comment>
@@ -705,7 +703,6 @@ Interaktívna konzola je teraz aktívna, napíšte "c" pre vstup do príkazovéh
<data name="ChecksumMissing" xml:space="preserve">
<value>Vzdialený server nepozná verziu na ktorú se snažíte aktualizovať. Táto situácia nastáva, pokiaľ verzia bola vydaná nedávno - aktualizácia nebude z bezpečnostných dôvodov pokračovať.</value>
</data>
<data name="ChecksumWrong" xml:space="preserve">
<value>Vzdialený server odpovedal s iným kontrolným súčtom, čo môže naznačovať chybu pri sťahovaní alebo útok MITM, proces aktualizácie preto nebude pokračovať!</value>
</data>
@@ -728,10 +725,6 @@ Interaktívna konzola je teraz aktívna, napíšte "c" pre vstup do príkazovéh
<value>ASF nemôže spustiť aplikáciu {0}, pretože má regionálne obmedzenie pre krajinu {1}, ktoré trvá do {2}.</value>
<comment>{0} will be replaced by app ID (number), {1} will be replaced by short country code (string, such as "PL"), {2} will be replaced by human-readable date (string).</comment>
</data>
<data name="PluginUpdatesChecking" xml:space="preserve">
<value>Kontrolujem aktualizácie pluginov...</value>
</data>
@@ -743,13 +736,10 @@ Interaktívna konzola je teraz aktívna, napíšte "c" pre vstup do príkazovéh
<value>Žiadne dostupné aktualizácie pre {0} plugin: {1} ≥ {2}.</value>
<comment>{0} will be replaced by plugin name (string), {1} will be replaced by current plugin's version, {2} will be replaced by remote plugin's version.</comment>
</data>
<data name="PluginUpdateFound" xml:space="preserve">
<value>Našla sa aktualizácia pre {0} plugin z verzie {1} na {2}...</value>
<comment>{0} will be replaced by plugin name (string), {1} will be replaced by current plugin's version, {2} will be replaced by remote plugin's version.</comment>
</data>
<data name="PluginUpdateInProgress" xml:space="preserve">
<value>Aktualizujem {0} plugin...</value>
<comment>{0} will be replaced by plugin name (string).</comment>
@@ -762,7 +752,4 @@ Interaktívna konzola je teraz aktívna, napíšte "c" pre vstup do príkazovéh
<value>{0}/{1} plugin bol zaregistrovaný a automatické aktualizácie boli aktivované.</value>
<comment>{0} will be replaced by plugin name (string), {1} will be replaced by plugin assembly name (string).</comment>
</data>
</root>

View File

@@ -87,7 +87,6 @@ StackTrace:
{2}</value>
<comment>{0} will be replaced by function name, {1} will be replaced by exception message, {2} will be replaced by entire stack trace. Please note that this string should include newlines for formatting.</comment>
</data>
<data name="ErrorFailingRequest" xml:space="preserve">
<value>Zahtev se ne izvršava: {0}</value>
<comment>{0} will be replaced by URL of the request</comment>
@@ -231,8 +230,6 @@ StackTrace:
<value>Trenutno radi {0}/{1} botova, a preostalo je ukupno {2} igrica ({3} karata) koje treba farmati.</value>
<comment>{0} will be replaced by number of active bots, {1} will be replaced by total number of bots, {2} will be replaced by total number of games left to farm, {3} will be replaced by total number of cards left to farm</comment>
</data>
<data name="CheckingFirstBadgePage" xml:space="preserve">
<value>Proveravanje prve stranje bedževa...</value>
</data>
@@ -246,11 +243,9 @@ StackTrace:
<data name="Done" xml:space="preserve">
<value>Gotovo!</value>
</data>
<data name="IdlingFinished" xml:space="preserve">
<value>Idlovanje je završeno!</value>
</data>
<data name="IdlingFinishedForGames" xml:space="preserve">
<value>Završeno idlovanje igrica: {0}</value>
<comment>{0} will be replaced by list of the games (IDs, numbers), separated by a comma</comment>
@@ -401,7 +396,6 @@ StackTrace:
<value>U vlasništvu: {0} | {1}</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name</comment>
</data>
<data name="BotRateLimitExceeded" xml:space="preserve">
<value>Stopa ograničenja je prevazićena, pokušaćemo ponovo nakon {0} čekanja...</value>
<comment>{0} will be replaced by translated TimeSpan string (such as "25 minutes")</comment>
@@ -566,7 +560,6 @@ Vrijeme rada procesa: {1}</value>
<value>Bot ima nivo {0}.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ActivelyMatchingItems" xml:space="preserve">
<value>Podudaranje Steam itema, runda #{0}...</value>
<comment>{0} will be replaced by round number</comment>
@@ -619,7 +612,6 @@ Vrijeme rada procesa: {1}</value>
<value>Uspješno obavljeno/a {0} potvrda/e!</value>
<comment>{0} will be replaced by number of confirmations</comment>
</data>
<data name="UpdateCleanup" xml:space="preserve">
<value>Čišćenje starih fajlova nakon ažuriranja...</value>
</data>
@@ -651,38 +643,4 @@ Vrijeme rada procesa: {1}</value>
<data name="ErrorConfigDirectoryNotFound" xml:space="preserve">
<value>Nije pronađen config direktorijum, odustajanje!</value>
</data>
</root>

View File

@@ -801,4 +801,7 @@ Processens drifttid: {1}</value>
<value>Input: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Du har deklarerat --system-krävs, även om ditt operativsystem saknar nödvändiga beroenden för att den funktionen ska fungera. Överväg att installera dbus, men du kan också säkert ignorera denna varning om du inte behöver hämning för att fungera korrekt.</value>
</data>
</root>

View File

@@ -87,7 +87,6 @@ StackTrace:
{2}</value>
<comment>{0} will be replaced by function name, {1} will be replaced by exception message, {2} will be replaced by entire stack trace. Please note that this string should include newlines for formatting.</comment>
</data>
<data name="ErrorFailingRequest" xml:space="preserve">
<value>คำขอล้มเหลว: {0}</value>
<comment>{0} will be replaced by URL of the request</comment>
@@ -125,7 +124,6 @@ StackTrace:
<data name="ErrorUpdateNoAssets" xml:space="preserve">
<value>ไม่สามารถดำเนินการอัพเดตได้เนื่อจากเวอร์ชั่นดังกล่าวไม่มีแอทเซทซใดๆอยู่!</value>
</data>
<data name="Exiting" xml:space="preserve">
<value>กำลังออก…</value>
</data>
@@ -185,7 +183,6 @@ StackTrace:
<value>เวอร์ชันบนเครื่อง: {0} | เวอร์ชันบนเซิร์ฟเวอร์: {1}</value>
<comment>{0} will be replaced by current version, {1} will be replaced by remote version</comment>
</data>
<data name="UserInputSteam2FA" xml:space="preserve">
<value>โปรดป้อนรหัส 2FA ของคุณจากแอปยืนยันตัวตน Steam ของคุณ: </value>
<comment>Please note that this translation should end with space</comment>
@@ -206,7 +203,6 @@ StackTrace:
<value>โปรดป้อนรหัสผ่าน Steam ขอบคุณ: </value>
<comment>Please note that this translation should end with space</comment>
</data>
<data name="IPCReady" xml:space="preserve">
<value>เซิร์ฟเวอร์ IPC พร้อมแล้ว!</value>
</data>
@@ -220,8 +216,6 @@ StackTrace:
<value>ไม่พบบอตชื่อ {0}!</value>
<comment>{0} will be replaced by bot's name query (string)</comment>
</data>
<data name="BotStatusIdlingList" xml:space="preserve">
<value>บอตกำลังฟาร์มเกม: เหลือให้ฟาร์ม {0} จากทั้งหมด {1} เกม (การ์ด {2} ใบ) (อีก ~{3})</value>
<comment>{0} will be replaced by list of the games (IDs, numbers), {1} will be replaced by total number of games to farm, {2} will be replaced by total number of cards to farm, {3} will be replaced by translated TimeSpan string (such as "1 day, 5 hours and 30 minutes")</comment>
@@ -261,7 +255,6 @@ StackTrace:
<data name="IdlingStopped" xml:space="preserve">
<value>การฟาร์มหยุดแล้ว!</value>
</data>
<data name="NothingToIdle" xml:space="preserve">
<value>บัญชีนี้ไม่มีอะไรให้เราฟาร์มเลย!</value>
</data>
@@ -273,7 +266,6 @@ StackTrace:
<value>กำลังฟาร์ม: {0}</value>
<comment>{0} will be replaced by list of the games (IDs, numbers), separated by a comma</comment>
</data>
<data name="StillIdling" xml:space="preserve">
<value>ยังคงฟาร์ม: {0} ({1})</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name</comment>
@@ -293,8 +285,6 @@ StackTrace:
<data name="UnknownCommand" xml:space="preserve">
<value>ไม่รู้จักคำสั่งนี้!</value>
</data>
<data name="BotAcceptingGift" xml:space="preserve">
<value>กำลังยอมรับของขวัญ: {0}...</value>
<comment>{0} will be replaced by giftID (number)</comment>
@@ -316,7 +306,6 @@ StackTrace:
<data name="BotAuthenticatorConverting" xml:space="preserve">
<value>กำลังแปลง .maFile ให้เป็นฟอร์แมตสำหรับ ASF...</value>
</data>
<data name="BotAuthenticatorToken" xml:space="preserve">
<value>โทเคน 2FA: {0}</value>
<comment>{0} will be replaced by generated 2FA token (string)</comment>
@@ -342,8 +331,6 @@ StackTrace:
<data name="BotDisconnecting" xml:space="preserve">
<value>กำลังตัดการเชื่อมต่อ...</value>
</data>
<data name="BotLoggedOff" xml:space="preserve">
<value>ออกจากระบบ Steam แล้ว: {0}</value>
<comment>{0} will be replaced by logging off reason (string)</comment>
@@ -355,18 +342,15 @@ StackTrace:
<data name="BotLoggingIn" xml:space="preserve">
<value>กำลังเข้าสู่ระบบ...</value>
</data>
<data name="BotLootingFailed" xml:space="preserve">
<value>ข้อเสนอแลกเปลี่ยนล้มเหลว!</value>
</data>
<data name="BotLootingSuccess" xml:space="preserve">
<value>ส่งข้อเสนอแลกเปลี่ยนสำเร็จ!</value>
</data>
<data name="BotSendingTradeToYourself" xml:space="preserve">
<value>ไม่สามารถส่งข้อเสนอแลกเปลี่ยนให้ตัวเองได้!</value>
</data>
<data name="BotNotConnected" xml:space="preserve">
<value>อินสแตนซ์ของบอตตัวนี้ไม่ได้รับการเชื่อมต่อ!</value>
</data>
@@ -382,7 +366,6 @@ StackTrace:
<value>แต้มคงเหลือ: {0}</value>
<comment>{0} will be replaced by the points balance value (integer)</comment>
</data>
<data name="BotReconnecting" xml:space="preserve">
<value>กำลังเชื่อมต่อใหม่...</value>
</data>
@@ -434,34 +417,20 @@ StackTrace:
<data name="BotConnectionLost" xml:space="preserve">
<value>สูญเสียการเชื่อมต่อกับ Steam Network กำลังเชื่อมต่อใหม่...</value>
</data>
<data name="BotConnecting" xml:space="preserve">
<value>กำลังเชื่อมต่อ...</value>
</data>
<data name="BotStopping" xml:space="preserve">
<value>กำลังหยุด...</value>
</data>
<data name="Initializing" xml:space="preserve">
<value>กำลังเริ่ม {0}...</value>
<comment>{0} will be replaced by service name that is being initialized</comment>
</data>
<data name="BotVersion" xml:space="preserve">
<value>{0} V{1}</value>
<comment>{0} will be replaced by program's name (e.g. "ASF"), {1} will be replaced by program's version (e.g. "1.0.0.0"). This string typically has nothing to translate and you should leave it as it is, unless you need to change the format, e.g. in RTL languages.</comment>
</data>
<data name="BotOwnedAlready" xml:space="preserve">
<value>เป็นเจ้าของแล้ว: {0}</value>
<comment>{0} will be replaced by game's ID (number), {1} will be replaced by game's name</comment>
@@ -469,19 +438,14 @@ StackTrace:
<data name="ErrorAccessDenied" xml:space="preserve">
<value>ปฏิเสธการเข้าถึง!</value>
</data>
<data name="BotStats" xml:space="preserve">
<value>การใช้หน่วยความจําปัจจุบัน: {0} MB.
เวลาทํางานของกระบวนการ: {1}</value>
<comment>{0} will be replaced by number (in megabytes) of memory being used, {1} will be replaced by translated TimeSpan string (such as "25 minutes"). Please note that this string should include newlines for formatting.</comment>
</data>
<data name="BotRefreshingPackagesData" xml:space="preserve">
<value>กำลังรีเฟรชข้อมูลแพ็กเกจ…</value>
</data>
<data name="TargetBotNotConnected" xml:space="preserve">
<value>อินสแตนซ์ของบอตเป้าหมายไม่ได้รับการเชื่อมต่อ!</value>
</data>
@@ -496,13 +460,9 @@ StackTrace:
<value>บอตมีเลเวล {0}</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ErrorAborted" xml:space="preserve">
<value>ยกเลิกแล้ว!</value>
</data>
<data name="PluginLoaded" xml:space="preserve">
<value>{0} ถูกโหลดสำเร็จแล้ว!</value>
<comment>{0} will be replaced by the name of the custom ASF plugin</comment>
@@ -514,7 +474,6 @@ StackTrace:
<data name="NothingFound" xml:space="preserve">
<value>ไม่พบอะไรเลย!</value>
</data>
<data name="PleaseWait" xml:space="preserve">
<value>กรุณารอ...</value>
</data>
@@ -524,45 +483,24 @@ StackTrace:
<data name="Executing" xml:space="preserve">
<value>กำลังดำเนินการ...</value>
</data>
<data name="BotHandledConfirmations" xml:space="preserve">
<value>จัดการการยืนยันเป็นผลสำเร็จ {0} รายการ!</value>
<comment>{0} will be replaced by number of confirmations</comment>
</data>
<data name="UpdateCleanup" xml:space="preserve">
<value>กำลังลบไฟล์เก่าหลังการอัปเดต...</value>
</data>
<data name="Result" xml:space="preserve">
<value>ผลลัพธ์: {0}</value>
<comment>{0} will be replaced by generic result of various functions that use this string</comment>
</data>
<data name="BotIdlingSelectedGames" xml:space="preserve">
<value>กำลังเล่นเกมที่เลือกไว้ {0}: {1}</value>
<comment>{0} will be replaced by internal name of the config property (e.g. "GamesPlayedWhileIdle"), {1} will be replaced by comma-separated list of appIDs that user has chosen</comment>
</data>
<data name="FetchingChecksumFromRemoteServer" xml:space="preserve">
<value>กำลังดึงข้อมูล checksum จากเซิร์ฟเวอร์ระยะไกล...</value>
</data>
<data name="PatchingFiles" xml:space="preserve">
<value>กำลังแพตช์ไฟล์ ASF…</value>
</data>
@@ -570,24 +508,4 @@ StackTrace:
<value>โปรดกรอกคีย์รหัสลับของคุณ: </value>
<comment>Please note that this translation should end with space</comment>
</data>
</root>

View File

@@ -584,7 +584,10 @@
<value>Рівень бота {0}.</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="BotInventory" xml:space="preserve">
<value>{0}/{1} ({2}/{3}): {4} активів</value>
<comment>{0} will be replaced by appID (number), {1} will be replaced by contextID (number), {2} will be replaced by app's name (string), {3} will be replaced by name of the context (string), {4} will be replaced by number of assets in the specified inventory (number).</comment>
</data>
<data name="ActivelyMatchingItems" xml:space="preserve">
<value>Підбір предметів Steam, раунд #{0}...</value>
<comment>{0} will be replaced by round number</comment>
@@ -797,4 +800,7 @@
<value>Input: {0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>Ви оголосили --system-required, хоча у вашої ОС немає необхідних залежностей, щоб ця функція працювала. Розгляньте встановлення dbus, хоча також можна безпечно ігнорувати це попередження, якщо вам не потрібно гальмувати для належної роботи.</value>
</data>
</root>

View File

@@ -800,4 +800,7 @@
<value>输入:{0}</value>
<comment>{0} will be replaced by text input from the user.</comment>
</data>
<data name="WarningNoSystemRequiredLinuxDependencies" xml:space="preserve">
<value>您已声明--system-require, 尽管您的操作系统缺少该功能所需的依赖关系。 考虑安装 dbus ,不过如果你不需要抑制才能正常工作,你也可以安全地忽略这个警告。</value>
</data>
</root>

View File

@@ -87,7 +87,6 @@
{2}</value>
<comment>{0} will be replaced by function name, {1} will be replaced by exception message, {2} will be replaced by entire stack trace. Please note that this string should include newlines for formatting.</comment>
</data>
<data name="ErrorFailingRequest" xml:space="preserve">
<value>請求失敗:{0}</value>
<comment>{0} will be replaced by URL of the request</comment>
@@ -186,7 +185,6 @@
<value>本地版本:{0} | 遠端版本:{1}</value>
<comment>{0} will be replaced by current version, {1} will be replaced by remote version</comment>
</data>
<data name="UserInputSteam2FA" xml:space="preserve">
<value>請輸入您的 Steam 身份驗證器應用程式上顯示的雙重驗證代碼: </value>
<comment>Please note that this translation should end with space</comment>
@@ -578,7 +576,6 @@
<value>當前機械人的等級為 {0}。</value>
<comment>{0} will be replaced by bot's level</comment>
</data>
<data name="ActivelyMatchingItems" xml:space="preserve">
<value>正在匹配 Steam 物品,第 #{0} 輪……</value>
<comment>{0} will be replaced by round number</comment>
@@ -666,7 +663,6 @@
<data name="ErrorConfigDirectoryNotFound" xml:space="preserve">
<value>找不到配寘目錄,正在中止!</value>
</data>
<data name="AutomaticFileMigration" xml:space="preserve">
<value>{0} config file will be migrated to the latest syntax...</value>
<comment>{0} will be replaced with the relative path to the affected config file</comment>
@@ -675,7 +671,6 @@
<value>您的加密金鑰太短。 我們建議使用長度至少為{0} 個位元組(字元) 的檔案。</value>
<comment>{0} will be replaced by the number of bytes (characters) recommended</comment>
</data>
<data name="WarningDefaultCryptKeyUsedForEncryption" xml:space="preserve">
<value>您正在使用{1} 内容的{0} 設定,但您沒有提供自定義金鑰。 這完全破壞了保護因為ASF被迫使用自己的已知的金鑰。 您應該提供一個自定義密碼金鑰,以利用此設定提供的安全優勢。</value>
<comment>{0} will be replaced by the name of a particular setting (e.g. "AES"), {1} will be replaced by the name of the property (e.g. "SteamPassword")</comment>
@@ -695,7 +690,6 @@
<data name="ChecksumMissing" xml:space="preserve">
<value>遠程服務器對我們要更新的版本一無所知。如果該版本是最近發佈的,則可能出現這種情況-作為額外的安全措施,拒絕立即繼續更新過程。</value>
</data>
<data name="ChecksumWrong" xml:space="preserve">
<value>遠程服務器已回復不同的校驗和這可能表明下載已損壞或MITM攻擊拒絕繼續更新過程</value>
</data>
@@ -710,23 +704,4 @@
<value>未禁止IP地址{0}</value>
<comment>{0} will be replaced by an IP address which was requested to be unbanned from using IPC</comment>
</data>
</root>

View File

@@ -40,5 +40,5 @@ public interface IASF : IPlugin {
/// ASF will call this method right after global config initialization.
/// </summary>
/// <param name="additionalConfigProperties">Extra config properties made out of <see cref="JsonExtensionDataAttribute" />. Can be null if no extra properties are found.</param>
Task OnASFInit(IReadOnlyDictionary<string, JsonElement>? additionalConfigProperties = null);
public Task OnASFInit(IReadOnlyDictionary<string, JsonElement>? additionalConfigProperties = null);
}

View File

@@ -40,12 +40,12 @@ public interface IBot : IPlugin {
/// Doing so will allow the garbage collector to dispose the bot afterwards, refraining from doing so will create a "memory leak" by keeping the reference alive.
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
Task OnBotDestroy(Bot bot);
public Task OnBotDestroy(Bot bot);
/// <summary>
/// ASF will call this method after creating the bot object, e.g. after config creation.
/// Bot config is not yet available at this stage. This function will execute only once for every bot object.
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
Task OnBotInit(Bot bot);
public Task OnBotInit(Bot bot);
}

View File

@@ -39,17 +39,17 @@ public interface IBotCardsFarmerInfo : IPlugin {
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
/// <param name="farmedSomething">Bool value indicating whether the module has finished successfully, so when there was at least one card to drop, and nothing has interrupted us in the meantime.</param>
Task OnBotFarmingFinished(Bot bot, bool farmedSomething);
public Task OnBotFarmingFinished(Bot bot, bool farmedSomething);
/// <summary>
/// ASF will call this method when cards farming module is started on given bot instance. The module is started only when there are valid cards to drop, so this method won't be called when there is nothing to idle.
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
Task OnBotFarmingStarted(Bot bot);
public Task OnBotFarmingStarted(Bot bot);
/// <summary>
/// ASF will call this method when cards farming module is stopped on given bot instance. The stop could be a result of a natural finish, or other situations (e.g. Steam networking issues, user commands).
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
Task OnBotFarmingStopped(Bot bot);
public Task OnBotFarmingStopped(Bot bot);
}

View File

@@ -44,5 +44,5 @@ public interface IBotCommand2 : IPlugin {
/// <param name="args">Pre-parsed message using standard ASF delimiters.</param>
/// <param name="steamID">Optionally, steamID of the user who executed the command - may not be available with value of 0 (e.g. ASF API).</param>
/// <returns>Response to the command, or null/empty (as the task value) if the command isn't handled by this plugin.</returns>
Task<string?> OnBotCommand(Bot bot, EAccess access, string message, string[] args, ulong steamID = 0);
public Task<string?> OnBotCommand(Bot bot, EAccess access, string message, string[] args, ulong steamID = 0);
}

View File

@@ -39,11 +39,11 @@ public interface IBotConnection : IPlugin {
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
/// <param name="reason">Reason for disconnection, or <see cref="EResult.OK" /> if the disconnection was initiated by ASF (e.g. as a result of a command).</param>
Task OnBotDisconnected(Bot bot, EResult reason);
public Task OnBotDisconnected(Bot bot, EResult reason);
/// <summary>
/// ASF will call this method when bot successfully connects to Steam network.
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
Task OnBotLoggedOn(Bot bot);
public Task OnBotLoggedOn(Bot bot);
}

View File

@@ -41,5 +41,5 @@ public interface IBotCustomMachineInfoProvider : IPlugin {
/// <remarks>This method will be called with very limited amount of bot-related data, as it's used during bot initialization. We recommend to stick with <see cref="Bot.BotName" />, <see cref="Bot.BotConfig" /> and <see cref="Bot.BotDatabase" /> exclusively.</remarks>
/// <param name="bot">Bot object related to this callback.</param>
/// <returns><see cref="IMachineInfoProvider" /> that will be used for the particular bot. You can return null if you want to use default implementation.</returns>
Task<IMachineInfoProvider?> GetMachineInfoProvider(Bot bot);
public Task<IMachineInfoProvider?> GetMachineInfoProvider(Bot bot);
}

View File

@@ -39,5 +39,5 @@ public interface IBotFriendRequest : IPlugin {
/// <param name="bot">Bot object related to this callback.</param>
/// <param name="steamID">64-bit Steam identificator of the user that sent a friend request, or a group that the bot has been invited to.</param>
/// <returns>True if the request should be accepted as part of this plugin, false otherwise.</returns>
Task<bool> OnBotFriendRequest(Bot bot, ulong steamID);
public Task<bool> OnBotFriendRequest(Bot bot, ulong steamID);
}

View File

@@ -41,5 +41,5 @@ public interface IBotIdentity : IPlugin {
/// <param name="data">Full data received by ASF in the callback that relates to this bot (Steam) account.</param>
/// <param name="nickname">Parsed nickname set for this bot (Steam) account.</param>
/// <param name="avatarHash">Parsed hash of the avatar of this bot (Steam) account, as hex.</param>
Task OnSelfPersonaState(Bot bot, SteamFriends.PersonaStateCallback data, string? nickname, string? avatarHash);
public Task OnSelfPersonaState(Bot bot, SteamFriends.PersonaStateCallback data, string? nickname, string? avatarHash);
}

View File

@@ -42,5 +42,5 @@ public interface IBotMessage : IPlugin {
/// <param name="steamID">64-bit long unsigned integer of steamID executing the command.</param>
/// <param name="message">Message in its raw format.</param>
/// <returns>Response to the message, or null/empty (as the task value) for silence.</returns>
Task<string?> OnBotMessage(Bot bot, ulong steamID, string message);
public Task<string?> OnBotMessage(Bot bot, ulong steamID, string message);
}

View File

@@ -42,5 +42,5 @@ public interface IBotModules : IPlugin {
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
/// <param name="additionalConfigProperties">Extra config properties made out of <see cref="JsonExtensionDataAttribute" />. Can be null if no extra properties are found.</param>
Task OnBotInitModules(Bot bot, IReadOnlyDictionary<string, JsonElement>? additionalConfigProperties = null);
public Task OnBotInitModules(Bot bot, IReadOnlyDictionary<string, JsonElement>? additionalConfigProperties = null);
}

View File

@@ -40,12 +40,12 @@ public interface IBotSteamClient : IPlugin {
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
/// <param name="callbackManager">Callback manager object which can be used for establishing subscriptions to standard and custom callbacks.</param>
Task OnBotSteamCallbacksInit(Bot bot, CallbackManager callbackManager);
public Task OnBotSteamCallbacksInit(Bot bot, CallbackManager callbackManager);
/// <summary>
/// ASF will call this method right after bot initialization in order to allow you hooking custom SK2 client handlers into the SteamClient.
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
/// <returns>Collection of custom client handlers that are supposed to be hooked into the SteamClient by ASF. If you do not require any, just return null or empty collection.</returns>
Task<IReadOnlyCollection<ClientMsgHandler>?> OnBotSteamHandlersInit(Bot bot);
public Task<IReadOnlyCollection<ClientMsgHandler>?> OnBotSteamHandlersInit(Bot bot);
}

View File

@@ -42,5 +42,5 @@ public interface IBotTradeOffer2 : IPlugin {
/// <param name="tradeOffer">Trade offer related to this callback.</param>
/// <param name="asfResult">ASF result in regards to parsing this trade offer, can be useful for determining why it wasn't accepted as part of the core logic.</param>
/// <returns>True if the trade offer should be accepted as part of this plugin, false otherwise.</returns>
Task<bool> OnBotTradeOffer(Bot bot, TradeOffer tradeOffer, ParseTradeResult.EResult asfResult);
public Task<bool> OnBotTradeOffer(Bot bot, TradeOffer tradeOffer, ParseTradeResult.EResult asfResult);
}

View File

@@ -40,5 +40,5 @@ public interface IBotTradeOfferResults : IPlugin {
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
/// <param name="tradeResults">Trade results related to this callback.</param>
Task OnBotTradeOfferResults(Bot bot, IReadOnlyCollection<ParseTradeResult> tradeResults);
public Task OnBotTradeOfferResults(Bot bot, IReadOnlyCollection<ParseTradeResult> tradeResults);
}

View File

@@ -40,5 +40,5 @@ public interface IBotUserNotifications : IPlugin {
/// </summary>
/// <param name="bot">Bot object related to this callback.</param>
/// <param name="newNotifications">Collection containing those notification types that are new (that is, when new count > previous count of that notification type).</param>
Task OnBotUserNotifications(Bot bot, IReadOnlyCollection<UserNotificationsCallback.EUserNotification> newNotifications);
public Task OnBotUserNotifications(Bot bot, IReadOnlyCollection<UserNotificationsCallback.EUserNotification> newNotifications);
}

View File

@@ -37,5 +37,5 @@ public interface IBotsComparer : IPlugin {
/// Unless you know what you're doing, you should not implement this property yourself and let ASF decide.
/// </summary>
/// <returns>Comparer that will be used for the bots, as well as bot regexes.</returns>
StringComparer BotsComparer => StringComparer.Ordinal;
public StringComparer BotsComparer => StringComparer.Ordinal;
}

View File

@@ -39,5 +39,5 @@ public interface ICrossProcessSemaphoreProvider : IPlugin {
/// </summary>
/// <param name="resourceName">Unique resource name provided by ASF for identification purposes.</param>
/// <returns>Concrete implementation of <see cref="ICrossProcessSemaphore" /> providing required functionality. It's allowed to return null if you want to use ASF's default implementation for specified resource instead.</returns>
Task<ICrossProcessSemaphore?> GetCrossProcessSemaphore(string resourceName);
public Task<ICrossProcessSemaphore?> GetCrossProcessSemaphore(string resourceName);
}

View File

@@ -48,14 +48,14 @@ public interface IGitHubPluginUpdates : IPluginUpdates {
/// Boolean value that determines whether your plugin is able to update at the time of calling. You may provide false if, for example, you're inside a critical section and you don't want to update at this time, despite supporting updates otherwise.
/// This effectively skips unnecessary request to GitHub if you're certain that you're not interested in any updates right now.
/// </summary>
bool CanUpdate => true;
public bool CanUpdate => true;
/// <summary>
/// ASF will use this property as a target for GitHub updates. GitHub repository specified here must have valid releases that will be used for updates.
/// </summary>
/// <returns>Repository name in format of {Author}/{Repository}.</returns>
/// <example>JustArchiNET/ArchiSteamFarm</example>
string RepositoryName { get; }
public string RepositoryName { get; }
Task<Uri?> IPluginUpdates.GetTargetReleaseURL(Version asfVersion, string asfVariant, bool asfUpdate, GlobalConfig.EUpdateChannel updateChannel, bool forced) {
ArgumentNullException.ThrowIfNull(asfVersion);
@@ -104,7 +104,7 @@ public interface IGitHubPluginUpdates : IPluginUpdates {
/// - *.zip, if exactly one match is found
/// </remarks>
/// <returns>Target release asset from those provided that should be used for auto-update. You may return null if the update is unavailable, for example, because ASF version/variant is determined unsupported, or due to any other reason.</returns>
Task<ReleaseAsset?> GetTargetReleaseAsset(Version asfVersion, string asfVariant, Version newPluginVersion, IReadOnlyCollection<ReleaseAsset> releaseAssets) {
public Task<ReleaseAsset?> GetTargetReleaseAsset(Version asfVersion, string asfVariant, Version newPluginVersion, IReadOnlyCollection<ReleaseAsset> releaseAssets) {
ArgumentNullException.ThrowIfNull(asfVersion);
ArgumentException.ThrowIfNullOrEmpty(asfVariant);
ArgumentNullException.ThrowIfNull(newPluginVersion);

View File

@@ -38,7 +38,7 @@ public interface IPlugin {
/// </summary>
/// <returns>String that will be used as the name of this plugin.</returns>
[JsonInclude]
string Name { get; }
public string Name { get; }
/// <summary>
/// ASF will use this property as version indicator of your plugin to the user.
@@ -46,10 +46,10 @@ public interface IPlugin {
/// </summary>
/// <returns>Version that will be shown to the user when plugin is loaded.</returns>
[JsonInclude]
Version Version { get; }
public Version Version { get; }
/// <summary>
/// ASF will call this method right after plugin initialization.
/// </summary>
Task OnLoaded();
public Task OnLoaded();
}

Some files were not shown because too many files have changed in this diff Show More