Compare commits

..

284 Commits

Author SHA1 Message Date
JustArchi
941e19ecc5 Apparently people do not understand this part clear enough 2017-02-05 09:05:50 +01:00
JustArchi
e7b6cc7801 Misc 2017-02-05 09:02:27 +01:00
JustArchi
3edc89c34e Bump 2017-02-05 08:12:41 +01:00
Łukasz Domeradzki
d1af9d0495 Merge pull request #455 from JustArchi/l10n
New Crowdin translations
2017-02-05 08:09:02 +01:00
JustArchi
ba3a792ca4 Misc 2017-02-05 08:06:38 +01:00
JustArchi
dba6fdfeeb TradingPreferences.DontAcceptBotTrades 2017-02-05 07:51:04 +01:00
Łukasz Domeradzki
5835bcbd54 New translations 2017-02-04 23:20:48 +01:00
Łukasz Domeradzki
1df0abb494 New translations 2017-02-04 23:10:53 +01:00
Łukasz Domeradzki
d6097106d8 New translations 2017-02-04 23:10:50 +01:00
Łukasz Domeradzki
db56078494 New translations 2017-02-04 23:00:50 +01:00
Łukasz Domeradzki
8d7098bf76 New translations 2017-02-04 16:00:52 +01:00
Łukasz Domeradzki
5a6edb4e25 New translations 2017-02-03 23:21:07 +01:00
Łukasz Domeradzki
089363af1b New translations 2017-02-03 23:11:11 +01:00
Łukasz Domeradzki
e0450452ab New translations 2017-02-03 20:12:14 +01:00
Łukasz Domeradzki
1dd1f81884 New translations 2017-02-03 18:23:48 +01:00
Łukasz Domeradzki
182975ce21 New translations 2017-02-03 17:53:11 +01:00
Łukasz Domeradzki
65a838c117 New translations 2017-02-03 17:42:58 +01:00
Łukasz Domeradzki
df8f5febd8 New translations 2017-02-03 17:31:41 +01:00
Łukasz Domeradzki
7e696125e8 New translations 2017-02-03 17:21:52 +01:00
Łukasz Domeradzki
3b5a9c6029 New translations 2017-02-03 17:21:49 +01:00
Łukasz Domeradzki
d4ebe33394 New translations 2017-02-03 17:13:13 +01:00
Łukasz Domeradzki
de0862c597 New translations 2017-02-03 17:06:54 +01:00
Łukasz Domeradzki
4252184f37 New translations 2017-02-03 16:44:14 +01:00
Łukasz Domeradzki
bd99f3fdc3 New translations 2017-02-03 16:34:29 +01:00
Łukasz Domeradzki
c8343993c7 New translations 2017-02-03 16:12:27 +01:00
Łukasz Domeradzki
a917d0133b New translations 2017-02-03 16:12:24 +01:00
Łukasz Domeradzki
05b4b9e907 New translations 2017-02-03 12:23:35 +01:00
Łukasz Domeradzki
10dd737e5c New translations 2017-02-03 12:23:31 +01:00
Łukasz Domeradzki
3b0ebf4126 New translations 2017-02-03 11:22:35 +01:00
JustArchi
1fb980f2bf Misc 2017-02-03 10:01:10 +01:00
JustArchi
8926297614 WCFProtocol -> WCFBinding
More appropriate
2017-02-03 09:59:02 +01:00
JustArchi
72141c53a3 Cleanup + missing CG bits 2017-02-03 09:56:18 +01:00
JustArchi
24350dcba5 Closes #448
Everything works on Windows, pending tests on Mono
2017-02-03 09:54:09 +01:00
JustArchi
0d6942b8ec Modify TradingPreferences default to None
Since introducing automated API keys, we do not want to make AcceptDonations the default option.
Existing configs will not be changed anyway.
2017-02-03 08:57:42 +01:00
Łukasz Domeradzki
6c1d28c978 Translated 2017-02-02 22:12:10 +01:00
Łukasz Domeradzki
fef93c5907 New translations 2017-02-02 21:31:37 +01:00
Łukasz Domeradzki
27072c688c New translations 2017-02-02 21:21:09 +01:00
Łukasz Domeradzki
94aa422cb8 New translations 2017-02-02 21:21:04 +01:00
Łukasz Domeradzki
3188a56af5 New translations 2017-02-02 21:11:49 +01:00
Łukasz Domeradzki
d5b1073f78 New translations 2017-02-02 21:11:45 +01:00
Łukasz Domeradzki
61c3b2f9cf Translated 2017-02-02 20:53:17 +01:00
Łukasz Domeradzki
861c502cb4 Translated 2017-02-02 20:41:46 +01:00
Łukasz Domeradzki
c622218a70 Translated 2017-02-02 20:33:01 +01:00
Łukasz Domeradzki
9089029d16 New translations 2017-02-02 20:21:33 +01:00
Łukasz Domeradzki
335c26efbc Translated 2017-02-02 20:21:25 +01:00
Łukasz Domeradzki
1f11817a37 New translations 2017-02-02 20:14:20 +01:00
Łukasz Domeradzki
9e2dfef644 New translations 2017-02-02 20:14:13 +01:00
Łukasz Domeradzki
cd287a4831 Translated 2017-02-02 20:14:06 +01:00
JustArchi
bd9fde0799 Misc 2017-02-02 19:04:31 +01:00
JustArchi
fd3aca7cbb Bump 2017-02-02 18:45:45 +01:00
Łukasz Domeradzki
e560456d52 Merge pull request #451 from JustArchi/l10n
New Crowdin translations
2017-02-02 18:40:00 +01:00
JustArchi
3de44af605 Misc 2017-02-02 18:02:02 +01:00
JustArchi
5bbb546b8a Closes #454 2017-02-02 17:56:37 +01:00
JustArchi
b1ff0a34db Fix possible crash 2017-02-02 14:04:34 +01:00
Łukasz Domeradzki
6d5fef4260 New translations 2017-02-02 12:23:17 +01:00
Łukasz Domeradzki
58725f0866 New translations 2017-02-01 23:32:17 +01:00
Łukasz Domeradzki
d4cb9a326e New translations 2017-02-01 23:01:03 +01:00
Łukasz Domeradzki
81f19c8971 New translations 2017-02-01 22:21:53 +01:00
Łukasz Domeradzki
b94c381263 New translations 2017-02-01 22:21:50 +01:00
Łukasz Domeradzki
6edc7d21a6 New translations 2017-02-01 22:11:42 +01:00
Łukasz Domeradzki
9cd6801e67 New translations 2017-02-01 22:01:53 +01:00
Łukasz Domeradzki
ec5e34d664 New translations 2017-02-01 21:51:41 +01:00
Łukasz Domeradzki
15c8ada4fa New translations 2017-02-01 21:41:42 +01:00
Łukasz Domeradzki
8d6842430d New translations 2017-02-01 21:31:49 +01:00
Łukasz Domeradzki
1e172b3266 New translations 2017-02-01 21:21:54 +01:00
Łukasz Domeradzki
f89fe15e4d New translations 2017-02-01 21:15:50 +01:00
Łukasz Domeradzki
f6b0589920 New translations 2017-02-01 21:15:46 +01:00
Łukasz Domeradzki
94d29720df New translations 2017-02-01 21:02:22 +01:00
Łukasz Domeradzki
cc13e1d423 New translations 2017-02-01 20:52:26 +01:00
Łukasz Domeradzki
4c960f3850 New translations 2017-02-01 20:43:13 +01:00
Łukasz Domeradzki
7912142dd3 New translations 2017-02-01 20:31:04 +01:00
Łukasz Domeradzki
68c9eb8dcc New translations 2017-02-01 20:11:50 +01:00
Łukasz Domeradzki
f905123946 New translations 2017-02-01 20:01:48 +01:00
Łukasz Domeradzki
a35a5af795 New translations 2017-02-01 19:54:09 +01:00
Łukasz Domeradzki
39fec43f29 New translations 2017-02-01 19:42:09 +01:00
Łukasz Domeradzki
6072cd21f0 New translations 2017-02-01 19:23:30 +01:00
Łukasz Domeradzki
1edb25b8cd New translations 2017-02-01 19:20:31 +01:00
Łukasz Domeradzki
94e18257b6 New translations 2017-02-01 19:02:35 +01:00
Łukasz Domeradzki
f938a2b21f New translations 2017-02-01 18:51:38 +01:00
Łukasz Domeradzki
91009af8f8 New translations 2017-02-01 18:42:21 +01:00
Łukasz Domeradzki
922f2476b3 Translated 2017-02-01 18:26:26 +01:00
Łukasz Domeradzki
b8e07ce765 Translated 2017-02-01 18:12:00 +01:00
Łukasz Domeradzki
58b1e5f92a New translations 2017-02-01 18:03:26 +01:00
Łukasz Domeradzki
c813e464fb Translated 2017-02-01 18:03:17 +01:00
Łukasz Domeradzki
3e837c9689 New translations 2017-02-01 17:52:30 +01:00
Łukasz Domeradzki
83baf9be92 Translated 2017-02-01 17:52:25 +01:00
Łukasz Domeradzki
67726e0dee New translations 2017-02-01 17:42:35 +01:00
Łukasz Domeradzki
cdd5bfd307 New translations 2017-02-01 17:32:13 +01:00
Łukasz Domeradzki
c2c262ea09 New translations 2017-02-01 17:32:10 +01:00
Łukasz Domeradzki
111d3c4cd5 New translations 2017-02-01 17:03:11 +01:00
Łukasz Domeradzki
de7f4f2857 New translations 2017-02-01 16:52:27 +01:00
Łukasz Domeradzki
66c8b32b8e New translations 2017-02-01 16:41:54 +01:00
Łukasz Domeradzki
09e738771b New translations 2017-02-01 16:32:37 +01:00
JustArchi
7d0d370330 Support case insensitivity for ASF matching 2017-02-01 15:35:03 +01:00
Łukasz Domeradzki
52fc58006d Translated 2017-02-01 15:23:45 +01:00
Łukasz Domeradzki
70952ad17e Translated 2017-02-01 14:14:07 +01:00
Łukasz Domeradzki
7e3a9dbb7c Translated 2017-02-01 14:06:21 +01:00
Łukasz Domeradzki
6fea823060 Translated 2017-02-01 14:06:18 +01:00
Łukasz Domeradzki
7cbfa24e7f Translated 2017-02-01 13:52:47 +01:00
JustArchi
245c04f7c5 Add more aliases 2017-02-01 13:02:47 +01:00
JustArchi
53c865d42b Add support for bot1..botN syntax 2017-02-01 12:20:49 +01:00
JustArchi
fa99281d49 Misc 2017-02-01 11:53:59 +01:00
Łukasz Domeradzki
88a0124ff0 Translated 2017-02-01 11:32:37 +01:00
Łukasz Domeradzki
5ee5dfb9b4 Translated 2017-02-01 11:32:29 +01:00
Łukasz Domeradzki
4c0971399c Translated 2017-02-01 11:21:50 +01:00
Łukasz Domeradzki
5dce8bed4c Translated 2017-02-01 11:02:22 +01:00
Łukasz Domeradzki
57cfac8e78 Translated 2017-02-01 11:02:16 +01:00
Łukasz Domeradzki
5854605446 Translated 2017-02-01 11:02:06 +01:00
JustArchi
5293b69261 Bring back no bots found + statusall extra response 2017-02-01 10:54:34 +01:00
Łukasz Domeradzki
f8f5df4e0e Translated 2017-02-01 09:02:27 +01:00
Łukasz Domeradzki
758bf868b2 Translated 2017-02-01 08:50:54 +01:00
Łukasz Domeradzki
f8f1de285f Translated 2017-02-01 08:50:52 +01:00
Łukasz Domeradzki
38112387ba Translated 2017-02-01 08:50:49 +01:00
Łukasz Domeradzki
3696f14e9a Translated 2017-02-01 08:11:40 +01:00
Łukasz Domeradzki
56ca507ca7 Translated 2017-02-01 06:02:21 +01:00
Łukasz Domeradzki
025e008bcb Translated 2017-02-01 03:00:55 +01:00
Łukasz Domeradzki
7659f5a994 Translated 2017-02-01 03:00:50 +01:00
Łukasz Domeradzki
23f2a5c269 Translated 2017-02-01 02:50:54 +01:00
Łukasz Domeradzki
d5aa87fe93 Translated 2017-02-01 02:50:50 +01:00
Łukasz Domeradzki
77a6461eb4 Translated 2017-02-01 02:20:54 +01:00
Łukasz Domeradzki
67a50ee6c1 Translated 2017-02-01 02:12:13 +01:00
Łukasz Domeradzki
368a19e76f Translated 2017-02-01 02:12:09 +01:00
Łukasz Domeradzki
23b722ebe0 Translated 2017-02-01 01:30:54 +01:00
Łukasz Domeradzki
5365ad09ba Translated 2017-02-01 01:21:58 +01:00
Łukasz Domeradzki
de5f5ae908 Translated 2017-02-01 01:21:56 +01:00
JustArchi
60eb99d4fd Bump 2017-02-01 00:53:38 +01:00
Łukasz Domeradzki
677e60328c Merge pull request #447 from JustArchi/l10n
New Crowdin translations
2017-02-01 00:52:02 +01:00
JustArchi
d5e865dff3 Misc 2017-02-01 00:49:49 +01:00
JustArchi
fb4cda513b Don't wait for bot being stopped too long 2017-02-01 00:44:52 +01:00
Łukasz Domeradzki
c3007d2d8f Translated 2017-01-31 22:42:45 +01:00
Łukasz Domeradzki
805f8d621b Translated 2017-01-31 22:42:42 +01:00
Łukasz Domeradzki
fb606b4459 Approved. Step name: Proofread 2017-01-31 22:42:37 +01:00
Łukasz Domeradzki
085d1a7290 Approved. Step name: Proofread 2017-01-31 22:42:35 +01:00
JustArchi
8e7ebfd2d1 Keep alphabetical order when targetting ASF commands 2017-01-31 22:32:38 +01:00
Łukasz Domeradzki
515ddedfd1 New translations 2017-01-31 22:32:06 +01:00
Łukasz Domeradzki
431621a125 Translated 2017-01-31 22:32:02 +01:00
JustArchi
ec697c2681 Remove obsolete commands 2017-01-31 22:27:16 +01:00
Łukasz Domeradzki
cece83e75d New translations 2017-01-31 22:24:08 +01:00
Łukasz Domeradzki
ed27bcf034 New translations 2017-01-31 22:24:05 +01:00
Łukasz Domeradzki
39301469ce New translations 2017-01-31 22:24:03 +01:00
Łukasz Domeradzki
83041622ad New translations 2017-01-31 22:24:00 +01:00
Łukasz Domeradzki
abbde82ab3 New translations 2017-01-31 22:23:58 +01:00
Łukasz Domeradzki
5c03d463ea New translations 2017-01-31 22:23:56 +01:00
Łukasz Domeradzki
cc1b47d765 New translations 2017-01-31 22:23:54 +01:00
Łukasz Domeradzki
720a6d1e32 New translations 2017-01-31 22:23:52 +01:00
Łukasz Domeradzki
6e8e8d2d39 Translated 2017-01-31 22:23:50 +01:00
Łukasz Domeradzki
6b0c894268 New translations 2017-01-31 22:23:48 +01:00
Łukasz Domeradzki
5a61512af6 New translations 2017-01-31 22:23:44 +01:00
Łukasz Domeradzki
9f6af19712 New translations 2017-01-31 22:23:42 +01:00
Łukasz Domeradzki
d882fe1a29 New translations 2017-01-31 22:23:39 +01:00
Łukasz Domeradzki
e4ce791e27 New translations 2017-01-31 22:23:38 +01:00
Łukasz Domeradzki
52128fd549 New translations 2017-01-31 22:23:35 +01:00
Łukasz Domeradzki
e5700e5518 New translations 2017-01-31 22:23:32 +01:00
Łukasz Domeradzki
a22079f38c New translations 2017-01-31 22:23:29 +01:00
Łukasz Domeradzki
4b0f5d2dad New translations 2017-01-31 22:23:26 +01:00
Łukasz Domeradzki
e9d8de9031 New translations 2017-01-31 22:23:24 +01:00
Łukasz Domeradzki
a5763ba1a8 New translations 2017-01-31 22:23:21 +01:00
Łukasz Domeradzki
77e5f98f37 New translations 2017-01-31 22:23:19 +01:00
Łukasz Domeradzki
23353fe1c1 New translations 2017-01-31 22:23:17 +01:00
Łukasz Domeradzki
1ee5d00486 New translations 2017-01-31 22:23:14 +01:00
Łukasz Domeradzki
3650af0a94 New translations 2017-01-31 22:23:12 +01:00
Łukasz Domeradzki
445e3ad9d4 Translated 2017-01-31 22:23:08 +01:00
JustArchi
69b829e883 Bump 2017-01-31 22:15:56 +01:00
Łukasz Domeradzki
71d9bcb5a0 New translations 2017-01-31 22:13:06 +01:00
Łukasz Domeradzki
ea38ead992 New translations 2017-01-31 22:13:04 +01:00
Łukasz Domeradzki
9101b0dc13 New translations 2017-01-31 22:13:02 +01:00
Łukasz Domeradzki
897dd9012f New translations 2017-01-31 22:12:59 +01:00
Łukasz Domeradzki
d3f3151ceb New translations 2017-01-31 22:12:56 +01:00
Łukasz Domeradzki
80129464ac Translated 2017-01-31 22:12:54 +01:00
Łukasz Domeradzki
5bf62ec4df Translated 2017-01-31 22:12:51 +01:00
Łukasz Domeradzki
9ea3e18c28 Translated 2017-01-31 22:12:49 +01:00
Łukasz Domeradzki
bfa3bdcaf0 Translated 2017-01-31 22:12:46 +01:00
Łukasz Domeradzki
3a2f0078f7 Translated 2017-01-31 22:12:44 +01:00
Łukasz Domeradzki
35ff24b28e Translated 2017-01-31 22:12:42 +01:00
Łukasz Domeradzki
0e22b0a577 Translated 2017-01-31 22:12:39 +01:00
Łukasz Domeradzki
b0efae7171 Translated 2017-01-31 22:12:37 +01:00
Łukasz Domeradzki
64d07b4764 Translated 2017-01-31 22:12:35 +01:00
Łukasz Domeradzki
53eeb87225 Translated 2017-01-31 22:12:32 +01:00
Łukasz Domeradzki
a3b323741b New translations 2017-01-31 22:12:31 +01:00
Łukasz Domeradzki
7e71fd706a New translations 2017-01-31 22:12:29 +01:00
Łukasz Domeradzki
8cd1210ee4 Translated 2017-01-31 22:12:27 +01:00
Łukasz Domeradzki
7ea771f3fa Approved. Step name: Proofread 2017-01-31 22:12:25 +01:00
Łukasz Domeradzki
f5c19c4cd3 New translations 2017-01-31 22:12:23 +01:00
Łukasz Domeradzki
32c12b14e4 Translated 2017-01-31 22:12:20 +01:00
Łukasz Domeradzki
1a15bd7677 Translated 2017-01-31 22:12:18 +01:00
Łukasz Domeradzki
40747ae55d Approved. Step name: Proofread 2017-01-31 22:12:17 +01:00
Łukasz Domeradzki
0c2d08af47 Translated 2017-01-31 22:12:14 +01:00
Łukasz Domeradzki
aa0269f987 New translations 2017-01-31 22:12:12 +01:00
Łukasz Domeradzki
8f0dd4960a Approved. Step name: Proofread 2017-01-31 22:12:09 +01:00
Łukasz Domeradzki
46ce27e0fb Translated 2017-01-31 22:12:07 +01:00
Łukasz Domeradzki
0cbca1e36f Translated 2017-01-31 22:12:05 +01:00
JustArchi
a5c1b0c253 Unify ASF newline responses 2017-01-31 22:03:20 +01:00
Łukasz Domeradzki
4deeb0fb10 New translations 2017-01-31 21:43:12 +01:00
Łukasz Domeradzki
a33b7b2278 New translations 2017-01-31 21:43:10 +01:00
Łukasz Domeradzki
019e52dc99 New translations 2017-01-31 21:43:08 +01:00
Łukasz Domeradzki
e7360188d0 New translations 2017-01-31 21:43:07 +01:00
Łukasz Domeradzki
95b19e8f93 New translations 2017-01-31 21:43:05 +01:00
Łukasz Domeradzki
0617bd7713 New translations 2017-01-31 21:43:03 +01:00
Łukasz Domeradzki
94363d79a9 New translations 2017-01-31 21:43:01 +01:00
Łukasz Domeradzki
a3de120d24 New translations 2017-01-31 21:42:59 +01:00
Łukasz Domeradzki
b75cdf927b New translations 2017-01-31 21:42:57 +01:00
Łukasz Domeradzki
14476863bd Translated 2017-01-31 21:42:55 +01:00
Łukasz Domeradzki
5d5fe7b32a New translations 2017-01-31 21:42:54 +01:00
Łukasz Domeradzki
4ea3a2859f Translated 2017-01-31 21:42:52 +01:00
Łukasz Domeradzki
8ca9366416 Translated 2017-01-31 21:42:50 +01:00
Łukasz Domeradzki
5c78923d21 New translations 2017-01-31 21:42:47 +01:00
Łukasz Domeradzki
478c890105 Translated 2017-01-31 21:42:45 +01:00
Łukasz Domeradzki
f87bd605fa Translated 2017-01-31 21:42:43 +01:00
Łukasz Domeradzki
e5fd1b85c8 Translated 2017-01-31 21:42:41 +01:00
Łukasz Domeradzki
b604206fd6 Translated 2017-01-31 21:42:38 +01:00
Łukasz Domeradzki
9a9c85baca Translated 2017-01-31 21:42:36 +01:00
JustArchi
265d869b58 Looks like fixed, add auto-cleanup for IgnoredAppIDs 2017-01-31 21:37:34 +01:00
Łukasz Domeradzki
beb1b63611 New translations 2017-01-31 21:33:33 +01:00
Łukasz Domeradzki
51e4b2341f New translations 2017-01-31 21:33:30 +01:00
Łukasz Domeradzki
8a71c550dd New translations 2017-01-31 21:33:27 +01:00
Łukasz Domeradzki
d6e5140c9b New translations 2017-01-31 21:33:24 +01:00
Łukasz Domeradzki
be05a63d1e New translations 2017-01-31 21:33:21 +01:00
Łukasz Domeradzki
1101ebc9d1 New translations 2017-01-31 21:33:19 +01:00
Łukasz Domeradzki
a601977b0a New translations 2017-01-31 21:33:17 +01:00
Łukasz Domeradzki
23e1834d2e New translations 2017-01-31 21:33:15 +01:00
Łukasz Domeradzki
6c336dc4d7 Translated 2017-01-31 21:33:12 +01:00
Łukasz Domeradzki
32071078ff Translated 2017-01-31 21:33:10 +01:00
Łukasz Domeradzki
3254c99f59 Translated 2017-01-31 21:33:08 +01:00
Łukasz Domeradzki
af3ee45e7d Translated 2017-01-31 21:33:06 +01:00
Łukasz Domeradzki
6c3808ff80 Translated 2017-01-31 21:33:03 +01:00
Łukasz Domeradzki
6c49a9d756 New translations 2017-01-31 21:33:00 +01:00
Łukasz Domeradzki
2c1f3280dd New translations 2017-01-31 21:32:58 +01:00
Łukasz Domeradzki
945868d2f3 New translations 2017-01-31 21:32:56 +01:00
Łukasz Domeradzki
2f861d7645 New translations 2017-01-31 21:32:54 +01:00
Łukasz Domeradzki
49388c4c22 New translations 2017-01-31 21:32:52 +01:00
Łukasz Domeradzki
ee2aae9d4c Translated 2017-01-31 21:32:50 +01:00
Łukasz Domeradzki
a7420d14ea Approved. Step name: Proofread 2017-01-31 21:32:47 +01:00
Łukasz Domeradzki
df6a1785a1 New translations 2017-01-31 21:32:45 +01:00
Łukasz Domeradzki
bb7d7558ef New translations 2017-01-31 21:32:44 +01:00
Łukasz Domeradzki
b975b9d2bf Translated 2017-01-31 21:32:41 +01:00
Łukasz Domeradzki
8f3eb6382c Translated 2017-01-31 21:32:39 +01:00
Łukasz Domeradzki
6d37fa958c Translated 2017-01-31 21:32:37 +01:00
Łukasz Domeradzki
276cc6bfc5 Approved. Step name: Proofread 2017-01-31 21:32:35 +01:00
Łukasz Domeradzki
0ce2f00a16 Translated 2017-01-31 21:32:33 +01:00
Łukasz Domeradzki
99e07056ea Translated 2017-01-31 21:32:31 +01:00
Łukasz Domeradzki
17bfe74deb Translated 2017-01-31 21:32:28 +01:00
Łukasz Domeradzki
ef462b241c Approved. Step name: Proofread 2017-01-31 21:32:26 +01:00
Łukasz Domeradzki
0b4dc6ac7b Translated 2017-01-31 21:32:25 +01:00
Łukasz Domeradzki
daa0e02fbe Translated 2017-01-31 21:32:23 +01:00
Łukasz Domeradzki
deee1093b9 Approved. Step name: Proofread 2017-01-31 21:32:17 +01:00
Łukasz Domeradzki
cc407e5d2c Approved. Step name: Proofread 2017-01-31 21:32:14 +01:00
Łukasz Domeradzki
37f46043f9 Translated 2017-01-31 21:32:12 +01:00
Łukasz Domeradzki
4a856ac31e Translated 2017-01-31 21:32:10 +01:00
Łukasz Domeradzki
892ede79a1 Translated 2017-01-31 21:32:08 +01:00
Łukasz Domeradzki
d7c4bbc7a6 Translated 2017-01-31 21:32:06 +01:00
Łukasz Domeradzki
283b255886 New translations 2017-01-31 21:32:03 +01:00
Łukasz Domeradzki
a6ef3a9259 Translated 2017-01-31 21:32:00 +01:00
Łukasz Domeradzki
737f90ca43 Translated 2017-01-31 21:31:58 +01:00
Łukasz Domeradzki
7d21015df3 Translated 2017-01-31 21:31:56 +01:00
Łukasz Domeradzki
7e86cf269c Translated 2017-01-31 21:31:54 +01:00
Łukasz Domeradzki
10578d0844 Translated 2017-01-31 21:31:52 +01:00
Łukasz Domeradzki
28efaae76a New translations 2017-01-31 21:31:50 +01:00
Łukasz Domeradzki
3cb7116809 Translated 2017-01-31 21:31:48 +01:00
Łukasz Domeradzki
86bd5d8843 Translated 2017-01-31 21:31:46 +01:00
Łukasz Domeradzki
27d0c9de04 Translated 2017-01-31 21:31:44 +01:00
Łukasz Domeradzki
c610d5cb01 Translated 2017-01-31 21:31:42 +01:00
Łukasz Domeradzki
29d6846dae Translated 2017-01-31 21:31:39 +01:00
Łukasz Domeradzki
2597e1b9da Translated 2017-01-31 21:31:37 +01:00
Łukasz Domeradzki
d37908cb00 Translated 2017-01-31 21:31:35 +01:00
Łukasz Domeradzki
1ccbcd737a Translated 2017-01-31 21:31:33 +01:00
Łukasz Domeradzki
40c5c322c5 Translated 2017-01-31 21:31:31 +01:00
JustArchi
602eec3596 Let's hope this will be final fix 2017-01-31 21:24:18 +01:00
JustArchi
c426ddece7 Second fix attempt 2017-01-31 21:03:06 +01:00
JustArchi
4133254f7f Test 2017-01-31 20:57:56 +01:00
JustArchi
281577698b First fix attempt 2017-01-31 20:47:37 +01:00
JustArchi
10085f9dd4 Kill root cause of this annoying fuckup 2017-01-31 19:52:20 +01:00
JustArchi
3bf792eba5 Test 2017-01-31 19:09:48 +01:00
JustArchi
ac3bf2eb31 Test 2017-01-31 18:54:25 +01:00
Łukasz Domeradzki
e5c6ca120b Translated 2017-01-31 16:53:44 +01:00
Łukasz Domeradzki
3ddf03de7b Translated 2017-01-31 16:43:43 +01:00
Łukasz Domeradzki
9743786aeb New translations 2017-01-31 15:11:01 +01:00
Łukasz Domeradzki
d6293101ec Translated 2017-01-31 15:10:54 +01:00
Łukasz Domeradzki
b70bde0b94 New translations 2017-01-31 15:01:46 +01:00
Łukasz Domeradzki
b858acfb79 New translations 2017-01-31 13:27:55 +01:00
Łukasz Domeradzki
816efbd712 New translations 2017-01-31 13:17:22 +01:00
Łukasz Domeradzki
29fbde4533 New translations 2017-01-31 10:27:45 +01:00
JustArchi
71a9e25720 Bump 2017-01-31 10:21:14 +01:00
JustArchi
22f3ca4c4f Fix debugging directory 2017-01-31 10:06:27 +01:00
JustArchi
b6dd768c0b Bump 2017-01-31 09:32:02 +01:00
62 changed files with 1036 additions and 569 deletions

View File

@@ -324,6 +324,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AES/@EntryIndexedValue">AES</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=API/@EntryIndexedValue">API</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ASF/@EntryIndexedValue">ASF</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EWCF/@EntryIndexedValue">EWCF</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FA/@EntryIndexedValue">FA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FS/@EntryIndexedValue">FS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HTML/@EntryIndexedValue">HTML</s:String>
@@ -337,6 +338,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TTL/@EntryIndexedValue">TTL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=URL/@EntryIndexedValue">URL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WCF/@EntryIndexedValue">WCF</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WS/@EntryIndexedValue">WS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WTF/@EntryIndexedValue">WTF</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XML/@EntryIndexedValue">XML</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="I" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>

View File

@@ -330,7 +330,7 @@ namespace ArchiSteamFarm {
CreateBot(botName).Forget();
}
private static void OnDeleted(object sender, FileSystemEventArgs e) {
private static async void OnDeleted(object sender, FileSystemEventArgs e) {
if ((sender == null) || (e == null)) {
ArchiLogger.LogNullError(nameof(sender) + " || " + nameof(e));
return;
@@ -343,7 +343,7 @@ namespace ArchiSteamFarm {
if (botName.Equals(SharedInfo.ASF)) {
ArchiLogger.LogGenericError(Strings.ErrorGlobalConfigRemoved);
Program.Exit(1);
await Program.Exit(1).ConfigureAwait(false);
return;
}
@@ -353,7 +353,7 @@ namespace ArchiSteamFarm {
}
}
private static void OnRenamed(object sender, RenamedEventArgs e) {
private static async void OnRenamed(object sender, RenamedEventArgs e) {
if ((sender == null) || (e == null)) {
ArchiLogger.LogNullError(nameof(sender) + " || " + nameof(e));
return;
@@ -366,7 +366,7 @@ namespace ArchiSteamFarm {
if (oldBotName.Equals(SharedInfo.ASF)) {
ArchiLogger.LogGenericError(Strings.ErrorGlobalConfigRemoved);
Program.Exit(1);
await Program.Exit(1).ConfigureAwait(false);
return;
}
@@ -387,11 +387,11 @@ namespace ArchiSteamFarm {
if (Program.GlobalConfig.AutoRestart) {
ArchiLogger.LogGenericInfo(Strings.Restarting);
await Task.Delay(5000).ConfigureAwait(false);
Program.Restart();
await Program.Restart().ConfigureAwait(false);
} else {
ArchiLogger.LogGenericInfo(Strings.Exiting);
await Task.Delay(5000).ConfigureAwait(false);
Program.Exit();
await Program.Exit().ConfigureAwait(false);
}
}

View File

@@ -163,7 +163,7 @@ namespace ArchiSteamFarm {
SteamClient = new SteamClient(Program.GlobalConfig.SteamProtocol);
if (Program.GlobalConfig.Debug && Directory.Exists(SharedInfo.DebugDirectory)) {
string debugListenerPath = Path.Combine(SharedInfo.DebugDirectory);
string debugListenerPath = Path.Combine(SharedInfo.DebugDirectory, botName);
try {
Directory.CreateDirectory(debugListenerPath);
@@ -322,48 +322,6 @@ namespace ArchiSteamFarm {
}
}
internal async Task<HashSet<uint>> GetUnreleasedAppIDs(HashSet<uint> appIDs) {
if ((appIDs == null) || (appIDs.Count == 0)) {
ArchiLogger.LogNullError(nameof(appIDs));
return null;
}
AsyncJobMultiple<SteamApps.PICSProductInfoCallback>.ResultSet productInfo;
try {
productInfo = await SteamApps.PICSGetProductInfo(appIDs, Enumerable.Empty<uint>());
} catch (Exception e) {
ArchiLogger.LogGenericException(e);
return null;
}
HashSet<uint> result = new HashSet<uint>();
foreach (KeyValuePair<uint, SteamApps.PICSProductInfoCallback.PICSProductInfo> app in productInfo.Results.SelectMany(productResult => productResult.Apps)) {
if (!appIDs.Contains(app.Key)) {
continue;
}
string releaseState = app.Value.KeyValues["common"]["ReleaseState"].Value;
if (string.IsNullOrEmpty(releaseState)) {
continue;
}
switch (releaseState) {
case "released":
break;
case "prerelease":
case "preloadonly":
result.Add(app.Key);
break;
default:
ArchiLogger.LogGenericWarning(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(releaseState), releaseState));
break;
}
}
return result;
}
internal static async Task InitializeCMs(uint cellID, IServerListProvider serverListProvider) {
if (serverListProvider == null) {
ASF.ArchiLogger.LogNullError(nameof(serverListProvider));
@@ -385,6 +343,37 @@ namespace ArchiSteamFarm {
}
}
internal async Task<bool?> IsReleased(uint appID) {
if (appID == 0) {
ArchiLogger.LogNullError(nameof(appID));
return null;
}
AsyncJobMultiple<SteamApps.PICSProductInfoCallback>.ResultSet productInfo;
try {
productInfo = await SteamApps.PICSGetProductInfo(appID, null);
} catch (Exception e) {
ArchiLogger.LogGenericException(e);
return null;
}
foreach (string releaseState in productInfo.Results.SelectMany(productResult => productResult.Apps).Where(app => appID == app.Key).Select(app => app.Value.KeyValues["common"]["ReleaseState"].Value).Where(releaseState => !string.IsNullOrEmpty(releaseState))) {
switch (releaseState) {
case "released":
return true;
case "prerelease":
case "preloadonly":
return false;
default:
ArchiLogger.LogGenericWarning(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(releaseState), releaseState));
return null;
}
}
return null;
}
internal async Task LootIfNeeded() {
if (!BotConfig.SendOnFarmingFinished || (BotConfig.SteamMasterID == 0) || !IsConnectedAndLoggedOn || (BotConfig.SteamMasterID == SteamClient.SteamID)) {
return;
@@ -557,12 +546,10 @@ namespace ArchiSteamFarm {
return ResponseResume(steamID);
case "!RESTART":
return ResponseRestart(steamID);
case "!STARTALL":
return ResponseStartAll(steamID);
case "!SA":
return await ResponseStatus(steamID, SharedInfo.ASF).ConfigureAwait(false);
case "!STATUS":
return ResponseStatus(steamID);
case "!STATUSALL":
return ResponseStatusAll(steamID);
case "!STOP":
return ResponseStop(steamID);
case "!UPDATE":
@@ -594,6 +581,8 @@ namespace ArchiSteamFarm {
return await ResponseLoot(steamID, args[1]).ConfigureAwait(false);
case "!LOOT^":
return await ResponseLootSwitch(steamID, args[1]).ConfigureAwait(false);
case "!OA":
return await ResponseOwns(steamID, SharedInfo.ASF, args[1]).ConfigureAwait(false);
case "!OWNS":
if (args.Length > 2) {
return await ResponseOwns(steamID, args[1], args[2]).ConfigureAwait(false);
@@ -748,14 +737,40 @@ namespace ArchiSteamFarm {
HashSet<Bot> result = new HashSet<Bot>();
foreach (string botName in botNames.Where(botName => !string.IsNullOrEmpty(botName))) {
if (botName.Equals(SharedInfo.ASF)) {
foreach (Bot bot in Bots.Values) {
if (botName.Equals(SharedInfo.ASF, StringComparison.OrdinalIgnoreCase)) {
foreach (Bot bot in Bots.OrderBy(bot => bot.Key).Select(bot => bot.Value)) {
result.Add(bot);
}
return result;
}
if (botName.Contains("..")) {
string[] botRange = botName.Split(new[] { ".." }, StringSplitOptions.RemoveEmptyEntries);
if (botRange.Length == 2) {
Bot firstBot, lastBot;
if (Bots.TryGetValue(botRange[0], out firstBot) && Bots.TryGetValue(botRange[1], out lastBot)) {
bool inRange = false;
foreach (Bot bot in Bots.OrderBy(bot => bot.Key).Select(bot => bot.Value)) {
if (bot == firstBot) {
inRange = true;
} else if (!inRange) {
continue;
}
result.Add(bot);
if (bot == lastBot) {
break;
}
}
continue;
}
}
}
Bot targetBot;
if (!Bots.TryGetValue(botName, out targetBot)) {
continue;
@@ -825,7 +840,7 @@ namespace ArchiSteamFarm {
return;
}
if (++HeartBeatFailures >= (byte) Math.Ceiling(Program.GlobalConfig.ConnectionTimeout / 4.0)) {
if (++HeartBeatFailures >= (byte) Math.Ceiling(Program.GlobalConfig.ConnectionTimeout / 10.0)) {
HeartBeatFailures = byte.MaxValue;
ArchiLogger.LogGenericWarning(Strings.BotConnectionLost);
Connect(true).Forget();
@@ -1629,11 +1644,11 @@ namespace ArchiSteamFarm {
}
if (!HasMobileAuthenticator) {
return Strings.BotNoASFAuthenticator;
return Environment.NewLine + Strings.BotNoASFAuthenticator;
}
string token = await BotDatabase.MobileAuthenticator.GenerateToken().ConfigureAwait(false);
return !string.IsNullOrEmpty(token) ? string.Format(Strings.BotAuthenticatorToken, token) : Strings.WarningFailed;
return Environment.NewLine + (!string.IsNullOrEmpty(token) ? string.Format(Strings.BotAuthenticatorToken, token) : Strings.WarningFailed);
}
private static async Task<string> Response2FA(ulong steamID, string botNames) {
@@ -1644,7 +1659,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -1664,11 +1679,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private async Task<string> Response2FAConfirm(ulong steamID, bool confirm) {
@@ -1682,18 +1693,18 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
if (!HasMobileAuthenticator) {
return Strings.BotNoASFAuthenticator;
return Environment.NewLine + Strings.BotNoASFAuthenticator;
}
if (await AcceptConfirmations(confirm).ConfigureAwait(false)) {
return Strings.Success;
return Environment.NewLine + Strings.Success;
}
return Strings.WarningFailed;
return Environment.NewLine + Strings.WarningFailed;
}
private static async Task<string> Response2FAConfirm(ulong steamID, string botNames, bool confirm) {
@@ -1704,7 +1715,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -1724,11 +1735,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private async Task<string> ResponseAddLicense(ulong steamID, ICollection<uint> gameIDs) {
@@ -1742,29 +1749,38 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
StringBuilder result = new StringBuilder();
StringBuilder response = new StringBuilder();
foreach (uint gameID in gameIDs) {
SteamApps.FreeLicenseCallback callback = await SteamApps.RequestFreeLicense(gameID);
SteamApps.FreeLicenseCallback callback;
try {
callback = await SteamApps.RequestFreeLicense(gameID);
} catch (Exception e) {
ArchiLogger.LogGenericException(e);
response.Append(Environment.NewLine + string.Format(Strings.BotAddLicenseResponse, BotName, gameID, EResult.Timeout));
break;
}
if (callback == null) {
result.AppendLine(Environment.NewLine + string.Format(Strings.BotAddLicenseResponse, BotName, gameID, EResult.Timeout));
response.Append(Environment.NewLine + string.Format(Strings.BotAddLicenseResponse, BotName, gameID, EResult.Timeout));
break;
}
if (callback.GrantedApps.Count > 0) {
result.AppendLine(Environment.NewLine + string.Format(Strings.BotAddLicenseResponseWithItems, BotName, gameID, callback.Result, string.Join(", ", callback.GrantedApps)));
response.Append(Environment.NewLine + string.Format(Strings.BotAddLicenseResponseWithItems, BotName, gameID, callback.Result, string.Join(", ", callback.GrantedApps)));
} else if (callback.GrantedPackages.Count > 0) {
result.AppendLine(Environment.NewLine + string.Format(Strings.BotAddLicenseResponseWithItems, BotName, gameID, callback.Result, string.Join(", ", callback.GrantedPackages)));
response.Append(Environment.NewLine + string.Format(Strings.BotAddLicenseResponseWithItems, BotName, gameID, callback.Result, string.Join(", ", callback.GrantedPackages)));
} else if (await ArchiWebHandler.AddFreeLicense(gameID).ConfigureAwait(false)) {
result.AppendLine(Environment.NewLine + string.Format(Strings.BotAddLicenseResponseWithItems, BotName, gameID, EResult.OK, gameID));
response.Append(Environment.NewLine + string.Format(Strings.BotAddLicenseResponseWithItems, BotName, gameID, EResult.OK, gameID));
} else {
result.AppendLine(Environment.NewLine + string.Format(Strings.BotAddLicenseResponse, BotName, gameID, EResult.AccessDenied));
response.Append(Environment.NewLine + string.Format(Strings.BotAddLicenseResponse, BotName, gameID, EResult.AccessDenied));
}
}
return result.ToString();
return response.Length > 0 ? response.ToString() : null;
}
private async Task<string> ResponseAddLicense(ulong steamID, string games) {
@@ -1778,7 +1794,7 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
string[] gameIDs = games.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
@@ -1787,14 +1803,14 @@ namespace ArchiSteamFarm {
foreach (string game in gameIDs.Where(game => !string.IsNullOrEmpty(game))) {
uint gameID;
if (!uint.TryParse(game, out gameID)) {
return string.Format(Strings.ErrorParsingObject, nameof(gameID));
return Environment.NewLine + string.Format(Strings.ErrorParsingObject, nameof(gameID));
}
gamesToRedeem.Add(gameID);
}
if (gamesToRedeem.Count == 0) {
return string.Format(Strings.ErrorIsEmpty, nameof(gamesToRedeem));
return Environment.NewLine + string.Format(Strings.ErrorIsEmpty, nameof(gamesToRedeem));
}
return await ResponseAddLicense(steamID, gamesToRedeem).ConfigureAwait(false);
@@ -1808,7 +1824,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -1828,16 +1844,12 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private static string ResponseAPI(ulong steamID) {
if (steamID != 0) {
return IsOwner(steamID) ? GetAPIStatus() : null;
return IsOwner(steamID) ? Environment.NewLine + GetAPIStatus() : null;
}
ASF.ArchiLogger.LogNullError(nameof(steamID));
@@ -1857,10 +1869,10 @@ namespace ArchiSteamFarm {
// Schedule the task after some time so user can receive response
Task.Run(async () => {
await Task.Delay(1000).ConfigureAwait(false);
Program.Exit();
await Program.Exit().ConfigureAwait(false);
}).Forget();
return Strings.Done;
return Environment.NewLine + Strings.Done;
}
private async Task<string> ResponseFarm(ulong steamID) {
@@ -1874,12 +1886,12 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
await CardsFarmer.StopFarming().ConfigureAwait(false);
CardsFarmer.StartFarming().Forget();
return Strings.Done;
return Environment.NewLine + Strings.Done;
}
private static async Task<string> ResponseFarm(ulong steamID, string botNames) {
@@ -1890,7 +1902,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -1910,11 +1922,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private string ResponseHelp(ulong steamID) {
@@ -1927,7 +1935,7 @@ namespace ArchiSteamFarm {
return null;
}
return "https://github.com/" + SharedInfo.GithubRepo + "/wiki/Commands";
return Environment.NewLine + "https://github.com/" + SharedInfo.GithubRepo + "/wiki/Commands";
}
private async Task<string> ResponseLoot(ulong steamID) {
@@ -1941,39 +1949,39 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
if (!LootingAllowed) {
return Strings.BotLootingTemporarilyDisabled;
return Environment.NewLine + Strings.BotLootingTemporarilyDisabled;
}
if (BotConfig.SteamMasterID == 0) {
return Strings.BotLootingMasterNotDefined;
return Environment.NewLine + Strings.BotLootingMasterNotDefined;
}
if (BotConfig.SteamMasterID == SteamClient.SteamID) {
return Strings.BotLootingYourself;
return Environment.NewLine + Strings.BotLootingYourself;
}
if (BotConfig.LootableTypes.Count == 0) {
return Strings.BotLootingNoLootableTypes;
return Environment.NewLine + Strings.BotLootingNoLootableTypes;
}
await Trading.LimitInventoryRequestsAsync().ConfigureAwait(false);
HashSet<Steam.Item> inventory = await ArchiWebHandler.GetMySteamInventory(true, BotConfig.LootableTypes).ConfigureAwait(false);
if ((inventory == null) || (inventory.Count == 0)) {
return string.Format(Strings.ErrorIsEmpty, nameof(inventory));
return Environment.NewLine + string.Format(Strings.ErrorIsEmpty, nameof(inventory));
}
if (!await ArchiWebHandler.SendTradeOffer(inventory, BotConfig.SteamMasterID, BotConfig.SteamTradeToken).ConfigureAwait(false)) {
return Strings.BotLootingFailed;
return Environment.NewLine + Strings.BotLootingFailed;
}
await Task.Delay(3000).ConfigureAwait(false); // Sometimes we can be too fast for Steam servers to generate confirmations, wait a short moment
await AcceptConfirmations(true, Steam.ConfirmationDetails.EType.Trade, BotConfig.SteamMasterID).ConfigureAwait(false);
return Strings.BotLootingSuccess;
return Environment.NewLine + Strings.BotLootingSuccess;
}
private static async Task<string> ResponseLoot(ulong steamID, string botNames) {
@@ -1984,7 +1992,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2004,11 +2012,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private string ResponseLootSwitch(ulong steamID) {
@@ -2022,7 +2026,7 @@ namespace ArchiSteamFarm {
}
LootingAllowed = !LootingAllowed;
return LootingAllowed ? Strings.BotLootingNowEnabled : Strings.BotLootingNowDisabled;
return Environment.NewLine + (LootingAllowed ? Strings.BotLootingNowEnabled : Strings.BotLootingNowDisabled);
}
private static async Task<string> ResponseLootSwitch(ulong steamID, string botNames) {
@@ -2033,7 +2037,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2053,11 +2057,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private async Task<string> ResponseOwns(ulong steamID, string query) {
@@ -2071,7 +2071,7 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
Dictionary<uint, string> ownedGames;
@@ -2108,11 +2108,7 @@ namespace ArchiSteamFarm {
}
}
if (response.Length > 0) {
return response.ToString();
}
return Environment.NewLine + string.Format(Strings.BotNotOwnedYet, BotName, query);
return response.Length > 0 ? response.ToString() : Environment.NewLine + string.Format(Strings.BotNotOwnedYet, BotName, query);
}
private static async Task<string> ResponseOwns(ulong steamID, string botNames, string query) {
@@ -2123,7 +2119,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2143,11 +2139,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private string ResponsePassword(ulong steamID) {
@@ -2161,7 +2153,7 @@ namespace ArchiSteamFarm {
}
if (string.IsNullOrEmpty(BotConfig.SteamPassword)) {
return string.Format(Strings.ErrorIsEmpty, nameof(BotConfig.SteamPassword));
return Environment.NewLine + string.Format(Strings.ErrorIsEmpty, nameof(BotConfig.SteamPassword));
}
return Environment.NewLine + string.Format(Strings.BotEncryptedPassword, CryptoHelper.ECryptoMethod.AES, CryptoHelper.Encrypt(CryptoHelper.ECryptoMethod.AES, BotConfig.SteamPassword)) + Environment.NewLine + string.Format(Strings.BotEncryptedPassword, CryptoHelper.ECryptoMethod.ProtectedDataForCurrentUser, CryptoHelper.Encrypt(CryptoHelper.ECryptoMethod.ProtectedDataForCurrentUser, BotConfig.SteamPassword));
@@ -2175,7 +2167,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2195,11 +2187,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private async Task<string> ResponsePause(ulong steamID, bool sticky) {
@@ -2213,21 +2201,21 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
if (CardsFarmer.Paused) {
return Strings.BotAutomaticIdlingPausedAlready;
return Environment.NewLine + Strings.BotAutomaticIdlingPausedAlready;
}
await CardsFarmer.Pause(sticky).ConfigureAwait(false);
if (!SteamFamilySharingIDs.Contains(steamID)) {
return Strings.BotAutomaticIdlingNowPaused;
return Environment.NewLine + Strings.BotAutomaticIdlingNowPaused;
}
StartFamilySharingInactivityTimer();
return string.Format(Strings.BotAutomaticIdlingPausedWithCountdown, FamilySharingInactivityMinutes);
return Environment.NewLine + string.Format(Strings.BotAutomaticIdlingPausedWithCountdown, FamilySharingInactivityMinutes);
}
private static async Task<string> ResponsePause(ulong steamID, string botNames, bool sticky) {
@@ -2238,7 +2226,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2258,11 +2246,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private async Task<string> ResponsePlay(ulong steamID, HashSet<uint> gameIDs) {
@@ -2276,7 +2260,7 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
if (!CardsFarmer.Paused) {
@@ -2284,7 +2268,7 @@ namespace ArchiSteamFarm {
}
ArchiHandler.PlayGames(gameIDs);
return Strings.Done;
return Environment.NewLine + Strings.Done;
}
private async Task<string> ResponsePlay(ulong steamID, string games) {
@@ -2298,7 +2282,7 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
string[] gameIDs = games.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
@@ -2307,7 +2291,7 @@ namespace ArchiSteamFarm {
foreach (string game in gameIDs.Where(game => !string.IsNullOrEmpty(game))) {
uint gameID;
if (!uint.TryParse(game, out gameID)) {
return string.Format(Strings.ErrorParsingObject, nameof(gameID));
return Environment.NewLine + string.Format(Strings.ErrorParsingObject, nameof(gameID));
}
gamesToPlay.Add(gameID);
@@ -2318,7 +2302,7 @@ namespace ArchiSteamFarm {
}
if (gamesToPlay.Count == 0) {
return string.Format(Strings.ErrorIsEmpty, gamesToPlay);
return Environment.NewLine + string.Format(Strings.ErrorIsEmpty, gamesToPlay);
}
return await ResponsePlay(steamID, gamesToPlay).ConfigureAwait(false);
@@ -2332,7 +2316,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2352,11 +2336,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
[SuppressMessage("ReSharper", "FunctionComplexityOverflow")]
@@ -2371,7 +2351,7 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
bool forward = !redeemFlags.HasFlag(ERedeemFlags.SkipForwarding) && (redeemFlags.HasFlag(ERedeemFlags.ForceForwarding) || BotConfig.RedeemingPreferences.HasFlag(BotConfig.ERedeemingPreferences.Forwarding));
@@ -2521,7 +2501,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2541,11 +2521,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private static string ResponseRejoinChat(ulong steamID) {
@@ -2562,7 +2538,7 @@ namespace ArchiSteamFarm {
bot.JoinMasterChat();
}
return Strings.Done;
return Environment.NewLine + Strings.Done;
}
private static string ResponseRestart(ulong steamID) {
@@ -2578,10 +2554,10 @@ namespace ArchiSteamFarm {
// Schedule the task after some time so user can receive response
Task.Run(async () => {
await Task.Delay(1000).ConfigureAwait(false);
Program.Restart();
await Program.Restart().ConfigureAwait(false);
}).Forget();
return Strings.Done;
return Environment.NewLine + Strings.Done;
}
private string ResponseResume(ulong steamID) {
@@ -2595,16 +2571,16 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return Strings.BotNotConnected;
return Environment.NewLine + Strings.BotNotConnected;
}
if (!CardsFarmer.Paused) {
return Strings.BotAutomaticIdlingResumedAlready;
return Environment.NewLine + Strings.BotAutomaticIdlingResumedAlready;
}
StopFamilySharingInactivityTimer();
CardsFarmer.Resume(true);
return Strings.BotAutomaticIdlingNowResumed;
return Environment.NewLine + Strings.BotAutomaticIdlingNowResumed;
}
private static async Task<string> ResponseResume(ulong steamID, string botNames) {
@@ -2615,7 +2591,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2635,11 +2611,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private string ResponseStart(ulong steamID) {
@@ -2653,12 +2625,12 @@ namespace ArchiSteamFarm {
}
if (KeepRunning) {
return Strings.BotAlreadyRunning;
return Environment.NewLine + Strings.BotAlreadyRunning;
}
SkipFirstShutdown = true;
Start().Forget();
return Strings.Done;
return Environment.NewLine + Strings.Done;
}
private static async Task<string> ResponseStart(ulong steamID, string botNames) {
@@ -2669,7 +2641,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2689,28 +2661,7 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
}
private static string ResponseStartAll(ulong steamID) {
if (steamID == 0) {
ASF.ArchiLogger.LogNullError(nameof(steamID));
return null;
}
if (!IsOwner(steamID)) {
return null;
}
foreach (Bot bot in Bots.Values.Where(bot => !bot.KeepRunning)) {
bot.ResponseStart(steamID);
}
return Strings.Done;
return responses.Count > 0 ? string.Join("", responses) : null;
}
private string ResponseStatus(ulong steamID) {
@@ -2724,31 +2675,31 @@ namespace ArchiSteamFarm {
}
if (!IsConnectedAndLoggedOn) {
return string.Format(KeepRunning ? Strings.BotStatusNotConnected : Strings.BotStatusNotRunning, BotName);
return Environment.NewLine + string.Format(KeepRunning ? Strings.BotStatusNotConnected : Strings.BotStatusNotRunning, BotName);
}
if (PlayingBlocked) {
return string.Format(Strings.BotStatusPlayingNotAvailable, BotName);
return Environment.NewLine + string.Format(Strings.BotStatusPlayingNotAvailable, BotName);
}
if (CardsFarmer.Paused) {
return string.Format(Strings.BotStatusPaused, BotName);
return Environment.NewLine + string.Format(Strings.BotStatusPaused, BotName);
}
if (IsLimitedUser) {
return string.Format(Strings.BotStatusLimited, BotName);
return Environment.NewLine + string.Format(Strings.BotStatusLimited, BotName);
}
if (CardsFarmer.CurrentGamesFarming.Count == 0) {
return string.Format(Strings.BotsStatusNotIdling, BotName);
return Environment.NewLine + string.Format(Strings.BotsStatusNotIdling, BotName);
}
if (CardsFarmer.CurrentGamesFarming.Count > 1) {
return string.Format(Strings.BotStatusIdlingList, BotName, string.Join(", ", CardsFarmer.CurrentGamesFarming.Select(game => game.AppID)), CardsFarmer.GamesToFarm.Count, CardsFarmer.GamesToFarm.Sum(game => game.CardsRemaining), CardsFarmer.TimeRemaining.ToHumanReadable());
return Environment.NewLine + string.Format(Strings.BotStatusIdlingList, BotName, string.Join(", ", CardsFarmer.CurrentGamesFarming.Select(game => game.AppID)), CardsFarmer.GamesToFarm.Count, CardsFarmer.GamesToFarm.Sum(game => game.CardsRemaining), CardsFarmer.TimeRemaining.ToHumanReadable());
}
CardsFarmer.Game soloGame = CardsFarmer.CurrentGamesFarming.First();
return string.Format(Strings.BotStatusIdling, BotName, soloGame.AppID, soloGame.GameName, soloGame.CardsRemaining, CardsFarmer.GamesToFarm.Count, CardsFarmer.GamesToFarm.Sum(game => game.CardsRemaining), CardsFarmer.TimeRemaining.ToHumanReadable());
return Environment.NewLine + string.Format(Strings.BotStatusIdling, BotName, soloGame.AppID, soloGame.GameName, soloGame.CardsRemaining, CardsFarmer.GamesToFarm.Count, CardsFarmer.GamesToFarm.Sum(game => game.CardsRemaining), CardsFarmer.TimeRemaining.ToHumanReadable());
}
private static async Task<string> ResponseStatus(ulong steamID, string botNames) {
@@ -2759,7 +2710,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2783,23 +2734,14 @@ namespace ArchiSteamFarm {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
}
private static string ResponseStatusAll(ulong steamID) {
if (steamID == 0) {
ASF.ArchiLogger.LogNullError(nameof(steamID));
return null;
if (bots.Count < Bots.Count) {
return string.Join("", responses);
}
if (!IsOwner(steamID)) {
return null;
}
HashSet<Bot> botsRunning = new HashSet<Bot>(Bots.Values.Where(bot => bot.KeepRunning));
string extraResponse = string.Format(Strings.BotsStatusOverview, botsRunning.Count, Bots.Count, botsRunning.Sum(bot => bot.CardsFarmer.GamesToFarm.Count), botsRunning.Sum(bot => bot.CardsFarmer.GamesToFarm.Sum(game => game.CardsRemaining)));
HashSet<Bot> botsRunning = new HashSet<Bot>(Bots.Where(bot => bot.Value.KeepRunning).OrderBy(bot => bot.Key).Select(bot => bot.Value));
IEnumerable<string> statuses = botsRunning.Select(bot => bot.ResponseStatus(steamID));
return Environment.NewLine + string.Join(Environment.NewLine, statuses) + Environment.NewLine + string.Format(Strings.BotsStatusOverview, botsRunning.Count, Bots.Count, botsRunning.Sum(bot => bot.CardsFarmer.GamesToFarm.Count), botsRunning.Sum(bot => bot.CardsFarmer.GamesToFarm.Sum(game => game.CardsRemaining)));
return string.Join("", responses) + Environment.NewLine + extraResponse;
}
private string ResponseStop(ulong steamID) {
@@ -2813,11 +2755,11 @@ namespace ArchiSteamFarm {
}
if (!KeepRunning) {
return Strings.BotAlreadyStopped;
return Environment.NewLine + Strings.BotAlreadyStopped;
}
Stop();
return Strings.Done;
return Environment.NewLine + Strings.Done;
}
private static async Task<string> ResponseStop(ulong steamID, string botNames) {
@@ -2828,7 +2770,7 @@ namespace ArchiSteamFarm {
HashSet<Bot> bots = GetBots(botNames);
if ((bots == null) || (bots.Count == 0)) {
return null;
return IsOwner(steamID) ? Environment.NewLine + string.Format(Strings.BotNotFound, botNames.Replace(",", " || ")) : null;
}
ICollection<string> results;
@@ -2848,16 +2790,12 @@ namespace ArchiSteamFarm {
}
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result)));
if (responses.Count == 0) {
return null;
}
return Environment.NewLine + string.Join(Environment.NewLine, responses);
return responses.Count > 0 ? string.Join("", responses) : null;
}
private string ResponseUnknown(ulong steamID) {
if (steamID != 0) {
return IsMaster(steamID) ? Strings.UnknownCommand : null;
return IsMaster(steamID) ? Environment.NewLine + Strings.UnknownCommand : null;
}
ArchiLogger.LogNullError(nameof(steamID));
@@ -2875,7 +2813,7 @@ namespace ArchiSteamFarm {
}
await ASF.CheckForUpdate(true).ConfigureAwait(false);
return Strings.Done;
return Environment.NewLine + Strings.Done;
}
private string ResponseVersion(ulong steamID) {
@@ -2888,7 +2826,7 @@ namespace ArchiSteamFarm {
return null;
}
return "ASF V" + SharedInfo.Version;
return Environment.NewLine + "ASF V" + SharedInfo.Version;
}
private void SendMessageToChannel(ulong steamID, string message) {

View File

@@ -108,7 +108,7 @@ namespace ArchiSteamFarm {
internal readonly string SteamTradeToken = null;
[JsonProperty(Required = Required.DisallowNull)]
internal readonly ETradingPreferences TradingPreferences = ETradingPreferences.AcceptDonations;
internal readonly ETradingPreferences TradingPreferences = ETradingPreferences.None;
[JsonProperty]
internal string SteamLogin { get; set; }
@@ -193,7 +193,8 @@ namespace ArchiSteamFarm {
None = 0,
AcceptDonations = 1,
SteamTradeMatcher = 2,
MatchEverything = 4
MatchEverything = 4,
DontAcceptBotTrades = 8
}
}
}

View File

@@ -23,6 +23,7 @@
*/
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@@ -36,7 +37,9 @@ using Newtonsoft.Json;
namespace ArchiSteamFarm {
internal sealed class CardsFarmer : IDisposable {
private const byte HoursToBump = 2; // How many hours are required for restricted accounts
private const byte HoursToIgnore = 24; // How many hours we ignore unreleased appIDs and don't bother checking them again
private static readonly ConcurrentDictionary<uint, DateTime> IgnoredAppIDs = new ConcurrentDictionary<uint, DateTime>(); // Reserved for unreleased games
private static readonly HashSet<uint> UntrustedAppIDs = new HashSet<uint> { 440, 570, 730 };
[JsonProperty]
@@ -178,20 +181,6 @@ namespace ArchiSteamFarm {
return;
}
// Remove from our list all games that were not released yet
HashSet<uint> appIDs = new HashSet<uint>(GamesToFarm.Select(game => game.AppID));
HashSet<uint> unreleasedAppIDs = await Bot.GetUnreleasedAppIDs(appIDs).ConfigureAwait(false);
if ((unreleasedAppIDs != null) && (unreleasedAppIDs.Count > 0)) {
if (GamesToFarm.RemoveWhere(game => unreleasedAppIDs.Contains(game.AppID)) > 0) {
if (GamesToFarm.Count == 0) {
Bot.ArchiLogger.LogGenericInfo(Strings.NothingToIdle);
await Bot.OnFarmingFinished(false).ConfigureAwait(false);
return;
}
}
}
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.GamesToIdle, GamesToFarm.Count, GamesToFarm.Sum(game => game.CardsRemaining), TimeRemaining.ToHumanReadable()));
// This is the last moment for final check if we can farm
@@ -354,6 +343,17 @@ namespace ArchiSteamFarm {
continue;
}
DateTime lastPICSReport;
if (IgnoredAppIDs.TryGetValue(appID, out lastPICSReport)) {
if (lastPICSReport.AddHours(HoursToIgnore) < DateTime.UtcNow) {
// This game served its time as being ignored
IgnoredAppIDs.TryRemove(appID, out lastPICSReport);
} else {
// This game is still ignored
continue;
}
}
// Cards
HtmlNode progressNode = htmlNode.SelectSingleNode(".//span[@class='progress_info_bold']");
if (progressNode == null) {
@@ -526,29 +526,35 @@ namespace ArchiSteamFarm {
return false;
}
Bot.ArchiHandler.PlayGame(game.AppID, Bot.BotConfig.CustomGamePlayedWhileFarming);
DateTime endFarmingDate = DateTime.UtcNow.AddHours(Program.GlobalConfig.MaxFarmingTime);
bool success = true;
bool? keepFarming = await ShouldFarm(game).ConfigureAwait(false);
bool? isReleased = await Bot.IsReleased(game.AppID).ConfigureAwait(false);
while (keepFarming.GetValueOrDefault(true) && (DateTime.UtcNow < endFarmingDate)) {
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StillIdling, game.AppID, game.GameName));
if (isReleased.GetValueOrDefault(true)) {
Bot.ArchiHandler.PlayGame(game.AppID, Bot.BotConfig.CustomGamePlayedWhileFarming);
DateTime endFarmingDate = DateTime.UtcNow.AddHours(Program.GlobalConfig.MaxFarmingTime);
DateTime startFarmingPeriod = DateTime.UtcNow;
if (FarmResetEvent.Wait(60 * 1000 * Program.GlobalConfig.FarmingDelay)) {
FarmResetEvent.Reset();
success = KeepFarming;
bool? keepFarming = await ShouldFarm(game).ConfigureAwait(false);
while (keepFarming.GetValueOrDefault(true) && (DateTime.UtcNow < endFarmingDate)) {
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StillIdling, game.AppID, game.GameName));
DateTime startFarmingPeriod = DateTime.UtcNow;
if (FarmResetEvent.Wait(60 * 1000 * Program.GlobalConfig.FarmingDelay)) {
FarmResetEvent.Reset();
success = KeepFarming;
}
// Don't forget to update our GamesToFarm hours
game.HoursPlayed += (float) DateTime.UtcNow.Subtract(startFarmingPeriod).TotalHours;
if (!success) {
break;
}
keepFarming = await ShouldFarm(game).ConfigureAwait(false);
}
// Don't forget to update our GamesToFarm hours
game.HoursPlayed += (float) DateTime.UtcNow.Subtract(startFarmingPeriod).TotalHours;
if (!success) {
break;
}
keepFarming = await ShouldFarm(game).ConfigureAwait(false);
} else {
IgnoredAppIDs[game.AppID] = DateTime.UtcNow;
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IdlingGameNotReleasedYet, game.AppID, game.GameName));
}
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StoppedIdling, game.AppID, game.GameName));

View File

@@ -114,16 +114,6 @@ namespace ArchiSteamFarm {
}
}
internal int RemoveWhere(Predicate<T> match) {
Lock.EnterWriteLock();
try {
return HashSet.RemoveWhere(match);
} finally {
Lock.ExitWriteLock();
}
}
internal bool ReplaceIfNeededWith(ICollection<T> items) {
Lock.EnterUpgradeableReadLock();

View File

@@ -36,7 +36,7 @@ namespace ArchiSteamFarm {
ASF.ArchiLogger.LogGenericInfo(Strings.NoBotsAreRunning);
await Task.Delay(5000).ConfigureAwait(false);
Program.Exit();
await Program.Exit().ConfigureAwait(false);
}
internal static void OnPersonaState(Bot bot, SteamFriends.PersonaStateCallback callback) { }

View File

@@ -38,10 +38,6 @@ namespace ArchiSteamFarm {
internal const byte DefaultConnectionTimeout = 60;
internal const ushort DefaultWCFPort = 1242;
private const byte DefaultFarmingDelay = 15;
private const byte DefaultMaxFarmingTime = 10;
private const ProtocolType DefaultSteamProtocol = ProtocolType.Tcp;
// This is hardcoded blacklist which should not be possible to change
internal static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 267420, 303700, 335590, 368020, 425280, 480730, 566020 };
@@ -64,7 +60,7 @@ namespace ArchiSteamFarm {
internal readonly bool Debug = false;
[JsonProperty(Required = Required.DisallowNull)]
internal readonly byte FarmingDelay = DefaultFarmingDelay;
internal readonly byte FarmingDelay = 15;
[JsonProperty(Required = Required.DisallowNull)]
internal readonly byte GiftsLimiterDelay = 1;
@@ -82,7 +78,7 @@ namespace ArchiSteamFarm {
internal readonly byte LoginLimiterDelay = 10;
[JsonProperty(Required = Required.DisallowNull)]
internal readonly byte MaxFarmingTime = DefaultMaxFarmingTime;
internal readonly byte MaxFarmingTime = 10;
[JsonProperty(Required = Required.DisallowNull)]
internal readonly byte MaxTradeHoldDuration = 15;
@@ -97,11 +93,14 @@ namespace ArchiSteamFarm {
internal readonly ulong SteamOwnerID = 0;
[JsonProperty(Required = Required.DisallowNull)]
internal readonly ProtocolType SteamProtocol = DefaultSteamProtocol;
internal readonly ProtocolType SteamProtocol = ProtocolType.Tcp;
[JsonProperty(Required = Required.DisallowNull)]
internal readonly EUpdateChannel UpdateChannel = EUpdateChannel.Stable;
[JsonProperty(Required = Required.DisallowNull)]
internal readonly EWCFBinding WCFBinding = EWCFBinding.NetTcp;
[JsonProperty(Required = Required.DisallowNull)]
internal readonly ushort WCFPort = DefaultWCFPort;
@@ -182,5 +181,11 @@ namespace ArchiSteamFarm {
Stable,
Experimental
}
internal enum EWCFBinding : byte {
NetTcp,
BasicHttp,
WSHttp
}
}
}

View File

@@ -954,6 +954,15 @@ namespace ArchiSteamFarm.Localization {
}
}
/// <summary>
/// Looks up a localized string similar to Idling {0} ({1}) is temporarily disabled, as that game was not released yet..
/// </summary>
internal static string IdlingGameNotReleasedYet {
get {
return ResourceManager.GetString("IdlingGameNotReleasedYet", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Idling status for {0} ({1}): {2} cards remaining.
/// </summary>

View File

@@ -278,6 +278,7 @@
</root>

View File

@@ -350,6 +350,7 @@
</root>

View File

@@ -133,35 +133,67 @@
<value>Конфигурираното свойство {0} е невалидно: {1}</value>
<comment>{0} will be replaced by name of the configuration property, {1} will be replaced by invalid value</comment>
</data>
<data name="ErrorEarlyFatalExceptionInfo" xml:space="preserve">
<value>ASF V{0} претърпя критичен срив, преди основния записващ модул, да стартира!</value>
<comment>{0} will be replaced by version number</comment>
</data>
<data name="ErrorEarlyFatalExceptionPrint" xml:space="preserve">
<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="ErrorExitingWithNonZeroErrorCode" xml:space="preserve">
<value>Изключване при код за грешка различен от 0 (нула)!</value>
</data>
<data name="ErrorFailingRequest" xml:space="preserve">
<value>Провалена заявка: {0}</value>
<comment>{0} will be replaced by URL of the request</comment>
</data>
<data name="ErrorGlobalConfigNotLoaded" xml:space="preserve">
<value>Общата настройка не може да бъде заредена, моля уверете се, че {0} съществува и е валидна! Прочетете наръчника за настройване в wiki страницата, ако сте объркани.</value>
<comment>{0} will be replaced by file's path</comment>
</data>
<data name="ErrorIsInvalid" xml:space="preserve">
<value>{0} е невалидно!</value>
<value>{0} е невалиден!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorMobileAuthenticatorInvalidDeviceID" xml:space="preserve">
<value>Отказва да изпълни тази функцията, поради невалиден DeviceID в ASF 2FA!</value>
</data>
<data name="ErrorNoBotsDefined" xml:space="preserve">
<value>Няма настрени ботове, да не би да сте забравили да настроите ASF?</value>
</data>
<data name="ErrorObjectIsNull" xml:space="preserve">
<value>{0} е нулев!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorParsingObject" xml:space="preserve">
<value>Разборът {0} се провали!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorRemovingOldBinary" xml:space="preserve">
<value>Не може да се премахне старият ASF файл, моля премахнете {0} ръчно, за може обновлението да сработи!</value>
<comment>{0} will be replaced by file's path</comment>
</data>
<data name="ErrorRequestFailedTooManyTimes" xml:space="preserve">
<value>Операцията не може да се изпълни въпреки {0} опита!</value>
<comment>{0} will be replaced by maximum number of tries</comment>
</data>
<data name="ErrorUpdateCheckFailed" xml:space="preserve">
<value>Не успя да се провери за последната версия!</value>
</data>
<data name="ErrorUpdateNoAssetForThisBinary" xml:space="preserve">
<value>Не може да се премине към обновление, защото няма файл, който е свързан с работещата в момента програма! Моля проверете, че вашата ASF програма е именувана правилно!</value>
</data>
<data name="ErrorUpdateNoAssets" xml:space="preserve">
<value>Не може да се премине към обновление, защото тази версия не включва никакви файлове!</value>
</data>
<data name="ErrorUserInputRunningInHeadlessMode" xml:space="preserve">
<value>Получено е желание за промяна от потребителя, но процеса продължава в режим без възможност за промяна!</value>
</data>
<data name="ErrorWCFAccessDenied" xml:space="preserve">
<value>Отказване на желанието, защото SteamOwnerID не е зададено!</value>
<comment>SteamOwnerID is name of bot config property, it should not be translated</comment>
</data>
<data name="Exiting" xml:space="preserve">
<value>Излизане…</value>
</data>
@@ -170,11 +202,24 @@
</data>
<data name="IgnoringTrade" xml:space="preserve">
<value>Пренебрегване на замяната: {0}</value>
<comment>{0} will be replaced by trade number</comment>
</data>
<data name="LoggingIn" xml:space="preserve">
<value>Записване в {0}...</value>
<comment>{0} will be replaced by service's name</comment>
</data>
<data name="NoBotsAreRunning" xml:space="preserve">
<value>Не работят ботове, излизане...</value>
</data>
<data name="RefreshingOurSession" xml:space="preserve">
<value>Обновление на сесията!</value>
</data>
<data name="RejectingTrade" xml:space="preserve">
<value>Отказване на замяната: {0}</value>
<comment>{0} will be replaced by trade number</comment>
</data>
<data name="Restarting" xml:space="preserve">
<value>Рестартиране…</value>
</data>
@@ -182,8 +227,13 @@
<data name="Starting" xml:space="preserve">
<value>Стартиране...</value>
</data>
<data name="StatusCode" xml:space="preserve">
<value>Статус код: {0}</value>
<comment>{0} will be replaced by status code number/name</comment>
</data>
<data name="Success" xml:space="preserve">
<value>Успешно!</value>
</data>
@@ -234,20 +284,12 @@
<data name="Done" xml:space="preserve">
<value>Готово!</value>
<data name="WCFReady" xml:space="preserve">
<value>WSF сървърът е готов!</value>
</data>
<data name="WCFResponseReceived" xml:space="preserve">
<value>WCF отговор получен: {0}</value>
<comment>{0} will be replaced by WCF response</comment>
</data>
@@ -256,18 +298,68 @@
<data name="CheckingFirstBadgePage" xml:space="preserve">
<value>Проверяване на първата страница със значки...</value>
</data>
<data name="CheckingOtherBadgePages" xml:space="preserve">
<value>Проверяване на други страници със значки...</value>
</data>
<data name="ChosenFarmingAlgorithm" xml:space="preserve">
<value>Избиране на алгоритъм за вадене на карти: {0}</value>
<comment>{0} will be replaced by the name of chosen idling algorithm</comment>
</data>
<data name="Done" xml:space="preserve">
<value>Готово!</value>
</data>
<data name="IdlingFinished" xml:space="preserve">
<value>Изкарването на карти приключи!</value>
</data>
<data name="IdlingFinishedForGames" xml:space="preserve">
<value>Завърши ваденето на карти на: {0}</value>
<comment>{0} will be replaced by list of the games (appIDs, numbers), separated by a comma</comment>
</data>
<data name="IdlingStopped" xml:space="preserve">
<value>Изкарването на карти е спряно!</value>
</data>
<data name="NowIdling" xml:space="preserve">
<value>Сега се вадят карти на: {0} ({1})</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
<data name="NowIdlingList" xml:space="preserve">
<value>Сега се вадят карти на: {0}</value>
<comment>{0} will be replaced by list of the games (appIDs, 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 appID (number), {1} will be replaced by game's name</comment>
</data>
<data name="StillIdlingList" xml:space="preserve">
<value>Все още се вадят карти на: {0}</value>
<comment>{0} will be replaced by list of the games (appIDs, numbers), separated by a comma</comment>
</data>
<data name="StoppedIdling" xml:space="preserve">
<value>Прекратено е ваденето на карти на: {0} ({1})</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
<data name="StoppedIdlingList" xml:space="preserve">
<value>Прекратено е ваденето на карти на: {0}</value>
<comment>{0} will be replaced by list of the games (appIDs, numbers), separated by a comma</comment>
</data>
<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>
</data>
@@ -294,7 +386,7 @@
<data name="BotLoggedOn" xml:space="preserve">
<value>Влязли сте успешно!</value>
<value>Влезли сте успешно!</value>
</data>
<data name="BotLoggingIn" xml:space="preserve">
<value>Влизане…</value>
@@ -329,8 +421,14 @@
</data>
<data name="BotStatusNotConnected" xml:space="preserve">
<value>Бот {0} не е свързан.</value>
<comment>{0} will be replaced by bot's name</comment>
</data>
<data name="BotStatusNotRunning" xml:space="preserve">
<value>Бот {0} не работи.</value>
<comment>{0} will be replaced by bot's name</comment>
</data>
@@ -340,7 +438,7 @@
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="UnusedKeys" xml:space="preserve">
<value>Неизползваните ключове: {0}</value>
<value>Неизползвани ключове: {0}</value>
<comment>{0} will be replaced by list of cd-keys (strings), separated by a comma</comment>
</data>
<data name="WarningFailedWithError" xml:space="preserve">
@@ -362,11 +460,12 @@
<data name="Initializing" xml:space="preserve">
<value>Инициализиране {0}…</value>
<value>Стартиране {0}…</value>
<comment>{0} will be replaced by service name that is being initialized</comment>
</data>
</root>

View File

@@ -278,6 +278,7 @@
</root>

View File

@@ -697,4 +697,8 @@ StackTrace:
<value>ASF se pokusí použít váš preferovaný jazyk {0}. Překlad tohoto jazyka je ale dokončen pouze z {1}. Možná chcete pomoci zlepšit překlad aplikace ASF pro váš jazyk?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Farmení hry {0} ({1}) je dočasně zrušeno, protože hra zatím nevyšla.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -278,6 +278,7 @@
</root>

View File

@@ -541,7 +541,7 @@ StackTrace:
<value>Erfolgreich angemeldet!</value>
</data>
<data name="BotLoggingIn" xml:space="preserve">
<value>Melde an...</value>
<value>Anmelden...</value>
</data>
<data name="BotLogonSessionReplaced" xml:space="preserve">
<value>Dieses Benutzerkonto scheint bereits von einer anderen ASF-Instanz verwendet zu werden, welches ein undefiniertes Verhalten ist, verweigere es weiter laufen zu lassen!</value>
@@ -697,4 +697,8 @@ StackTrace:
<value>ASF wird versuchen deine bevorzugte {0} Sprache zu verwenden, jedoch wurde die Übersetzung in dieser Sprache nur zu {1} abgeschlossen. Kannst du uns vielleicht helfen die ASF-Übersetzung in deiner Sprache zu verbessern?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Sammeln {0} ({1}) ist vorübergehend deaktiviert, da dieses Spiel bis jetzt noch nicht veröffentlicht wurde.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -144,7 +144,7 @@ StackTrace:
<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="ErrorExitingWithNonZeroErrorCode" xml:space="preserve">
<value>Έξοδο με κωδικό σφάλματος μη μηδενική τιμή!</value>
<value>Έξοδο με κωδικό σφάλματος με μη μηδενική τιμή!</value>
</data>
<data name="ErrorFailingRequest" xml:space="preserve">
<value>Αποτυχία αίτησης: {0}</value>
@@ -173,11 +173,11 @@ StackTrace:
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorRemovingOldBinary" xml:space="preserve">
<value>Αδυναμία να αφαιρεθεί το παλιό ASF binary, παρακαλώ αφαιρέστε το {0} χειροκίνητα ώστε να λειτουργήσει η διαδικασία ενημέρωσης!</value>
<value>Αδυναμία αφαίρεσης του παλιού ASF binary, παρακαλώ αφαιρέστε το {0} χειροκίνητα ώστε να λειτουργήσει η λειτουργία ενημέρωσης!</value>
<comment>{0} will be replaced by file's path</comment>
</data>
<data name="ErrorRequestFailedTooManyTimes" xml:space="preserve">
<value>Η αίτηση απέτυχε παρά τις {0} προσπαθείες!</value>
<value>Το αίτημα απέτυχε παρά τις {0} προσπάθειες!</value>
<comment>{0} will be replaced by maximum number of tries</comment>
</data>
<data name="ErrorUpdateCheckFailed" xml:space="preserve">
@@ -220,7 +220,7 @@ StackTrace:
<value>Δεν τρέχει κανένα bot, τερματισμός...</value>
</data>
<data name="RefreshingOurSession" xml:space="preserve">
<value>Επανεκκίνηση της συνεδρίας!</value>
<value>Ανανέωση της συνεδρίας!</value>
</data>
<data name="RejectingTrade" xml:space="preserve">
<value>Απόρριψη ανταλλαγής: {0}</value>
@@ -696,4 +696,8 @@ StackTrace:
<value>Το ASF θα επιχειρήσει να χρησιμοποιήσει τη γλώσσα {0}, αλλά η μετάφραση σ'αυτή τη γλώσσα έχει συμπληρωθεί μόνο κατά {1}. Ισως θα μπορούσατε να μας βοηθήσετε να βελτιώσουμε τη μετάφραση του ASF για τη γλώσσα σας;</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Η συλλογή καρτών για το {0} ({1}) έχει απενεργοποιηθεί προσωρινά, καθώς το παιχνίδι δεν έχει κυκλοφορήσει ακόμα.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -697,4 +697,8 @@ StackTrace:
<value>ASF will attempt to use your preferred {0} culture, but translation in that language was completed only in {1}. Perhaps you could help us improve ASF translation for your language?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Idling {0} ({1}) is temporarily disabled, as that game was not released yet.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -696,4 +696,8 @@ Trazo de pila:
<value>ASF intentará utilizar tu idioma {0}, pero la traducción en este idioma está completa sólo en un {1}. ¿Tal vez podrías ayudarnos a mejorar la traducción de ASF para tu idioma?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>No se pueden aumentar las horas jugadas de {0} ({1}) porque el juego aún no ha salido.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -122,7 +122,7 @@
<comment>{0} will be replaced by trade number</comment>
</data>
<data name="AutoUpdateCheckInfo" xml:space="preserve">
<value>ASF tarkistaa automaattisesti uusia päivityksiä {0} tunnin välein.</value>
<value>ASF tarkistaa päivitykset automaattisesti {0} tunnin välein.</value>
<comment>{0} will be replaced by number of hours</comment>
</data>
<data name="Content" xml:space="preserve">
@@ -145,13 +145,15 @@
<data name="ErrorUpdateCheckFailed" xml:space="preserve">
<value>Viimeisimmän version tarkistus epäonnistui!</value>
</data>
<data name="Exiting" xml:space="preserve">
<value>Poistutaan...</value>
<value>Suljetaan...</value>
</data>
@@ -165,12 +167,19 @@
<value>Käynnistetään uudelleen...</value>
</data>
<data name="RuntimeVersionComparison" xml:space="preserve">
<value>Vaadittu versio: {0} | Nykyinen versio: {1}</value>
<comment>{0} will be replaced by required version, {1} will be replaced by current version</comment>
</data>
<data name="Starting" xml:space="preserve">
<value>Käynnistetään...</value>
</data>
<data name="Success" xml:space="preserve">
<value>Valmis!</value>
</data>
<data name="TimeSpanDay" xml:space="preserve">
<value>1 päivä</value>
</data>
@@ -235,61 +244,122 @@
<data name="WCFReady" xml:space="preserve">
<value>WCF-palvelin on valmiina!</value>
</data>
<data name="BotNotFound" xml:space="preserve">
<value>Bottia nimeltä {0} ei voitu löytää!</value>
<comment>{0} will be replaced by bot's name</comment>
</data>
<data name="CheckingFirstBadgePage" xml:space="preserve">
<value>Tarkastellaan ensimmäistä badge sivua...</value>
</data>
<data name="CheckingOtherBadgePages" xml:space="preserve">
<value>Tarkastellaan muita badge sivuja...</value>
</data>
<data name="ChosenFarmingAlgorithm" xml:space="preserve">
<value>Asetettu idlaus algoritmi: {0}</value>
<comment>{0} will be replaced by the name of chosen idling algorithm</comment>
</data>
<data name="Done" xml:space="preserve">
<value>Valmis!</value>
</data>
<data name="GamesToIdle" xml:space="preserve">
<value>In case there is only 1 game left to idle and only one card drop left, "peliä" should be "peli" and "korttia" should "kortti". Same goes for timestamps, if only 1 left its "minuutti, tunti, päivä, kuukausi
edit; also word "joissa" should be "jossa" if only card left
{0}{1}{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 built from TimeSpan* translation parts</comment>
</data>
<data name="IdlingFinished" xml:space="preserve">
<value>Idlaus valmis!</value>
</data>
<data name="IdlingFinishedForGame" xml:space="preserve">
<value>Idlaus valmis {0} ({1}) Kulunut aika: {2}!
I think this works alot better in finnish...</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name, {2} will be replaced by translated TimeSpan string built from TimeSpan* translation parts</comment>
</data>
<data name="IdlingStopped" xml:space="preserve">
<value>Idlaus pysäytetty!</value>
</data>
<data name="StillIdling" xml:space="preserve">
<value>Idlataan: {0} ({1})</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
<data name="StillIdlingList" xml:space="preserve">
<value>Idlataan: {0}</value>
<comment>{0} will be replaced by list of the games (appIDs, numbers), separated by a comma</comment>
</data>
<data name="StoppedIdling" xml:space="preserve">
<value>Idlaus pysäytetty: {0} ({1})</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
<data name="StoppedIdlingList" xml:space="preserve">
<value>Idlaus pysäytetty: {0}</value>
<comment>{0} will be replaced by list of the games (appIDs, numbers), separated by a comma</comment>
</data>
<data name="UnknownCommand" xml:space="preserve">
<value>Tuntematon komento!</value>
</data>
<data name="BotAcceptingGift" xml:space="preserve">
<value>Hyväksytään lahjaa: {0}...</value>
<comment>{0} will be replaced by giftID (number)</comment>
</data>
<data name="BotAuthenticatorInvalidDeviceID" xml:space="preserve">
<value>Sinun DeviceID on virheellinen tai sitä ei ole olemassa!</value>
</data>
<data name="BotAutomaticIdlingPausedWithCountdown" xml:space="preserve">
<value>Automaattinen idlaus on pysäytetty! Sinulla on {0} minuuttia aikaa käynnistää peli.</value>
<comment>{0} will be replaced by number of minutes</comment>
</data>
<data name="BotConnected" xml:space="preserve">
<value>Yhdistetty Steamiin!</value>
</data>
<data name="BotDisconnected" xml:space="preserve">
<value>Katkaistu yhteys Steamista!</value>
</data>
<data name="BotDisconnecting" xml:space="preserve">
<value>Katkaistaan yhteyttä...</value>
</data>
<data name="BotEncryptedPassword" xml:space="preserve">
<value>[{0}] salasana: {1}</value>
<comment>{0} will be replaced by password encryption method (string), {1} will be replaced by encrypted password using that method (string)</comment>
</data>
<data name="BotLoggedOn" xml:space="preserve">
<value>Onnistuneesti kirjauduttu sisään!</value>
</data>
<data name="BotLoggingIn" xml:space="preserve">
<value>Kirjaudutaan sisään...</value>
</data>
@@ -307,33 +377,61 @@
<data name="BotReconnecting" xml:space="preserve">
<value>Yhdistetään uudelleen...</value>
</data>
<data name="BotStatusNotConnected" xml:space="preserve">
<value>Botti {0} ei ole yhdistetty.</value>
<comment>{0} will be replaced by bot's name</comment>
</data>
<data name="BotStatusNotRunning" xml:space="preserve">
<value>Botti {0} ei ole käynnissä.</value>
<comment>{0} will be replaced by bot's name</comment>
</data>
<data name="ErrorIsEmpty" xml:space="preserve">
<value>{0} on tyhjä!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="UnusedKeys" xml:space="preserve">
<value>Käyttämättömät CD-keyt: {0}</value>
<comment>{0} will be replaced by list of cd-keys (strings), separated by a comma</comment>
</data>
<data name="BotConnectionLost" xml:space="preserve">
<value>Yhteys Steamin palvelimeen katkesi, yhdistetään uudelleen...</value>
</data>
<data name="BotAccountFree" xml:space="preserve">
<value>Suljit pelin, idlaus prosessi jatkuu!</value>
</data>
<data name="BotConnecting" xml:space="preserve">
<value>Yhdistetään...</value>
</data>
<data name="BotStopping" xml:space="preserve">
<value>Pysäytetään...</value>
</data>
<data name="Initializing" xml:space="preserve">
<value>Alustetaan {0}...</value>
<comment>{0} will be replaced by service name that is being initialized</comment>
</data>
<data name="Welcome" xml:space="preserve">
<value>Huomasin että käynnistit ohjelman ensimmäisen kerran, tervetuloa!</value>
</data>

View File

@@ -224,14 +224,14 @@ StackTrace :
<value>Rafraîchissement de notre session !</value>
</data>
<data name="RejectingTrade" xml:space="preserve">
<value>L'Offre : {0} est rejetée</value>
<value>Offre rejetée : {0}</value>
<comment>{0} will be replaced by trade number</comment>
</data>
<data name="Restarting" xml:space="preserve">
<value>Redémarrage...</value>
</data>
<data name="WarningRuntimeUnsupported" xml:space="preserve">
<value>ASF a détecté un environnement d'exécution en cours non pris en charge, le programme pourrait NE PAS fonctionner. Vous le lancer à vos propres risques et périls, et sans aide !</value>
<value>ASF a détecté un environnement d'exécution en cours non pris en charge, le programme pourrait NE PAS fonctionner. Vous le lancez à vos propres risques et périls, et sans aide !</value>
</data>
<data name="RuntimeVersionComparison" xml:space="preserve">
<value>Version requise : {0} | Version trouvée : {1}</value>
@@ -697,4 +697,8 @@ StackTrace :
<value>ASF va tenter dutiliser votre langage préféré {0}, mais la traduction dans ce langage est achevée seulement à {1}. Peut-être vous pourriez nous aider à améliorer la traduction ASF pour votre langue ?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>La collecte des cartes pour {0} ({1}) est temporairement désactivée, car ce jeu nest pas encore sorti.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -323,7 +323,10 @@ StackTrace:
<value>&lt;{0}&gt; בבקשה הזן את את סיסמת הPIN (סיסמה בעלת 4 ספרות) של הגדרות ההרות של סטים: </value>
<comment>{0} will be replaced by bot's name. Please note that this translation should end with space</comment>
</data>
<data name="UserInputSteamPassword" xml:space="preserve">
<value>lt&amp;;{0}&gt; הכנס בבקשה את סיסמת הסטים שלך:</value>
<comment>{0} will be replaced by bot's name. Please note that this translation should end with space</comment>
</data>
<data name="UserInputWCFHost" xml:space="preserve">
<value>&lt;{0} &gt;, נא להזין WCF host: </value>
@@ -450,7 +453,9 @@ StackTrace:
<value>מופע בוט זה פועל כבר!</value>
<comment>{0} will be replaced by bot's name</comment>
</data>
<data name="BotAuthenticatorConverting" xml:space="preserve">
<value>המרת .maFile לפורמט ASF</value>
</data>
<data name="BotAuthenticatorInvalidDeviceID" xml:space="preserve">
<value>ה- DeviceID שלך שגוי או אינו קיים!</value>
@@ -618,4 +623,5 @@ StackTrace:
<value>CurrentCulture שסופק אינו חוקי, ConfigGenerator תמשיך לפעול עם ברירת המחדל!</value>
</data>
</root>

View File

@@ -331,6 +331,7 @@
</root>

View File

@@ -379,4 +379,5 @@ StackTrace: {2}</value>
</data>
</root>

View File

@@ -695,4 +695,8 @@
<value>ASF akan mencoba untuk menggunakan bahasa {0} pilihan Anda, tetapi terjemahan dalam bahasa tersebut baru {1}. Mungkin Anda bisa membantu ASF untuk melengkapi terjemahan ke dalam bahasa Anda?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Pendiaman {0} ({1}) sementara dinonaktifkan, seperti permainan yang belum dirilis.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -692,7 +692,11 @@
<value>Il valore CurrentCulture che hai fornito non è valido, ASF continuerà ad utilizzare quello di default!</value>
</data>
<data name="TranslationIncomplete" xml:space="preserve">
<value>ASF proverà ad utilizzare la tua cultura preferita {0}, ma la traduzione in questa lingua é completa solo al {1}. Magari potresti aiutarci a migliorare la traduzione di ASF nella tua lingua?</value>
<value>ASF proverà ad utilizzare la tua lingua preferita {0}, ma la traduzione è completa solo al {1}. Forse potresti aiutarci a migliorare la traduzione di ASF nella tua lingua?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Idling di {0} ({1}) è temporaneamente disabilitato, poiché il gioco non è stato ancora rilasciato.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -690,5 +690,12 @@
<data name="ErrorInvalidCurrentCulture" xml:space="preserve">
<value>指定されたCurrentCultureが有効ではありません。ASFはデフォルトで実行されます</value>
</data>
<data name="TranslationIncomplete" xml:space="preserve">
<value>ASFはあなたの言語{0} の使用を試みますが、この言語の翻訳の完成度は{1} です。もしかしたらあなたが翻訳の向上を助けられるかもしれませんよ?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>このゲームはまだリリースされていないため、{0} ({1}) のアイドリングは一時的に無効になります。</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -699,4 +699,8 @@ ASF 실행 파일의 이름이 적절한지 확인하시기 바랍니다!</value
<value>ASF는 {0} 지역 언어를 사용하려고 시도했지만, 해당 언어의 번역이 {1}만 완료되어 있습니다. 혹시 당신의 언어로 ASF 번역을 개선하는 것을 도와줄 수 있나요?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>해당 게임이 아직 출시 전이므로, {0} ({1})의 농사가 일시적으로 비활성화 되었습니다.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -694,4 +694,8 @@
<value>ASF bandys naudoti jūsų pageidaujamą {0} kalbą, bet vertimas į tą kalba buvo užbaigtas tik {1}. Galbūt jūs galėtumėte mums padėti pagerinti ASF vertimą į šią kalbą?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Kortelių rinkimas iš {0}({1}) laikinai sustabdytas, nes žaidimas dar nėra išleistas.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -278,6 +278,7 @@
</root>

View File

@@ -151,7 +151,7 @@ StackTrace:
<comment>{0} will be replaced by URL of the request</comment>
</data>
<data name="ErrorGlobalConfigNotLoaded" xml:space="preserve">
<value>Globale configuratie kan niet worden geladen, check of het bestand {0} bestaat en of het geldig is! Volg de handleiding op de wiki als je niet weet je wat je moet doen.</value>
<value>Globale configuratie kan niet worden geladen, controleer of het bestand {0} bestaat en of het geldig is! Volg de handleiding op de wiki als je niet weet je wat je moet doen.</value>
<comment>{0} will be replaced by file's path</comment>
</data>
<data name="ErrorIsInvalid" xml:space="preserve">
@@ -162,18 +162,18 @@ StackTrace:
<value>Deze functie wordt niet uitgevoerd als gevolg van de ongeldige DeviceID in ASF 2FA!</value>
</data>
<data name="ErrorNoBotsDefined" xml:space="preserve">
<value>Geen bots zijn gedefineerd, ben je vergeten om ASF te configureren?</value>
<value>Er zijn geen bots gedefinieerd, ben je vergeten om ASF te configureren?</value>
</data>
<data name="ErrorObjectIsNull" xml:space="preserve">
<value>{0} is nul!</value>
<value>{0} is null!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorParsingObject" xml:space="preserve">
<value>Parsing {0} mislukt!</value>
<value>Verwerking van {0} mislukt!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorRemovingOldBinary" xml:space="preserve">
<value>Kan niet de oude ASF binary verwijderen, verwijder alsjeblieft {0} handmatig zodat de update-functie werkt!</value>
<value>Kon niet de oude ASF binary verwijderen, verwijder alsjeblieft {0} handmatig zodat de updatefunctie werkt!</value>
<comment>{0} will be replaced by file's path</comment>
</data>
<data name="ErrorRequestFailedTooManyTimes" xml:space="preserve">
@@ -181,10 +181,10 @@ StackTrace:
<comment>{0} will be replaced by maximum number of tries</comment>
</data>
<data name="ErrorUpdateCheckFailed" xml:space="preserve">
<value>Controleren op de laatste versie is mislukt!</value>
<value>Controle voor de laatste versie is mislukt!</value>
</data>
<data name="ErrorUpdateNoAssetForThisBinary" xml:space="preserve">
<value>Kan niet verdergaan met update omdat er geen bezit is dat gerelateerd is aan de momenteel actieve binary! Controleer of de ASF Binary de juiste naam heeft!</value>
<value>Kon niet verdergaan met update omdat er geen bestand bestaat dat gerelateerd is aan de momenteel actieve binary! Controleer of de ASF Binary de juiste naam heeft!</value>
</data>
<data name="ErrorUpdateNoAssets" xml:space="preserve">
<value>Kan niet verdergaan met update omdat deze versie niet alle bestanden omvat!</value>
@@ -203,13 +203,13 @@ StackTrace:
<value>Mislukt!</value>
</data>
<data name="GlobalConfigChanged" xml:space="preserve">
<value>Globale configuratie bestand is gewijzigd!</value>
<value>Globaal configuratiebestand is aangepast!</value>
</data>
<data name="ErrorGlobalConfigRemoved" xml:space="preserve">
<value>Globale configuratie bestand is verwijderd!</value>
<value>Globaal configuratiebestand is verwijderd!</value>
</data>
<data name="IgnoringTrade" xml:space="preserve">
<value>Trade wordt genegeerd: {0}</value>
<value>Ruilaanbieding {0} wordt genegeerd</value>
<comment>{0} will be replaced by trade number</comment>
</data>
<data name="LoggingIn" xml:space="preserve">
@@ -217,23 +217,23 @@ StackTrace:
<comment>{0} will be replaced by service's name</comment>
</data>
<data name="NoBotsAreRunning" xml:space="preserve">
<value>Er zijn geen bots actief, afsluiten...</value>
<value>Geen bots actief, afsluiten...</value>
</data>
<data name="RefreshingOurSession" xml:space="preserve">
<value>Sessie wordt ververst!</value>
</data>
<data name="RejectingTrade" xml:space="preserve">
<value>Trade wordt afgekeurd: {0}</value>
<value>Ruilaanbieding {0} wordt afgekeurd</value>
<comment>{0} will be replaced by trade number</comment>
</data>
<data name="Restarting" xml:space="preserve">
<value>Herstarten...</value>
</data>
<data name="WarningRuntimeUnsupported" xml:space="preserve">
<value>ASF heeft een niet ondersteunde runtime versie gedetecteerd, het programma kan mogelijk NIET correct worden uitgevoerd in de huidige omgeving. Je voert dit met je eigen risico uit zonder ondersteuning!</value>
<value>ASF heeft een niet ondersteunde runtime versie gedetecteerd, het programma kan mogelijk NIET correct worden uitgevoerd in de huidige omgeving. Je voert dit met eigen risico en zonder ondersteuning uit!</value>
</data>
<data name="RuntimeVersionComparison" xml:space="preserve">
<value>Benodigde versie: {0} | Gevonden versie: {1}</value>
<value>Vereiste versie: {0} | Gevonden versie: {1}</value>
<comment>{0} will be replaced by required version, {1} will be replaced by current version</comment>
</data>
<data name="RuntimeVersionOK" xml:space="preserve">
@@ -289,13 +289,13 @@ StackTrace:
<value>Controleren op nieuwe versie...</value>
</data>
<data name="UpdateDownloadingNewVersion" xml:space="preserve">
<value>Nieuwe versie wordt gedownloadt.... Terwijl je aan het wachten bent, het wordt heel veel gewaardeerd als je een donatie geeft</value>
<value>Nieuwe versie wordt gedownloadt... Onder het wachten, overweeg te doneren als je het gedane werk waardeert! :)</value>
</data>
<data name="UpdateFinished" xml:space="preserve">
<value>Bijwerken afgerond!</value>
</data>
<data name="UpdateNewVersionAvailable" xml:space="preserve">
<value>Nieuwe ASF versie beschikbaar! Overweeg om handmatig bij te werken!</value>
<value>Nieuwe ASF-versie beschikbaar! Overweeg zelf bij te werken!</value>
</data>
<data name="UpdateVersionInfo" xml:space="preserve">
<value>Lokale versie: {0} | Externe versie: {1}</value>
@@ -696,4 +696,8 @@ StackTrace:
<value>ASF probeert de {0} taal te gebruiken, maar het vertalen in deze taal was tot {1} compleet. Misschien kan je ons helpen om ASF te vertalen in jouw taal?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Idling {0} ({1}) is tijdelijk uitgeschakeld, aangezien dat spel nog niet was uitgegeven.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -363,4 +363,5 @@
</root>

View File

@@ -697,4 +697,8 @@ StackTrace:
<value>ASF spróbuje użyć twojej preferowanej kultury {0}, ale tłumaczenie w tym języku zostało ukończone tylko w {1}. Być może mógłbyś pomóc nam w poprawieniu tłumaczenia ASF na Twój język?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Farmienie {0} ({1}) jest tymczasowo niemożliwe, jako że ta gra nie została jeszcze wydana.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -126,11 +126,12 @@
<comment>{0} will be replaced by number of hours</comment>
</data>
<data name="Content" xml:space="preserve">
<value>Conteúdo: {0}</value>
<value>Conteúdo:
{0}</value>
<comment>{0} will be replaced by content string. Please note that this string should include newline for formatting.</comment>
</data>
<data name="ErrorConfigPropertyInvalid" xml:space="preserve">
<value>Configuração {0} inválida com a propriedade: {1}</value>
<value>A propriedade {0} possui valor inválido: {1}</value>
<comment>{0} will be replaced by name of the configuration property, {1} will be replaced by invalid value</comment>
</data>
<data name="ErrorEarlyFatalExceptionInfo" xml:space="preserve">
@@ -169,7 +170,7 @@ StackTrace:
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorParsingObject" xml:space="preserve">
<value>Falha em analisar o {0}!</value>
<value>Falha ao analisar {0}!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorRemovingOldBinary" xml:space="preserve">
@@ -302,7 +303,7 @@ StackTrace:
<comment>{0} will be replaced by current version, {1} will be replaced by remote version</comment>
</data>
<data name="UserInputDeviceID" xml:space="preserve">
<value>&lt;{0}&gt; Insira seu ID do dispositivo (incluindo "android:"): </value>
<value>&lt;{0}&gt; Insira o ID do dispositivo do autenticador móvel (incluindo "android:"): </value>
<comment>{0} will be replaced by bot's name. Please note that this translation should end with space</comment>
</data>
<data name="UserInputSteam2FA" xml:space="preserve">
@@ -353,18 +354,18 @@ StackTrace:
<comment>{0} will be replaced by WCF command, {1} will be replaced by WCF answer</comment>
</data>
<data name="WCFReady" xml:space="preserve">
<value>O servidor WCF está pronto!</value>
<value>Servidor WCF pronto!</value>
</data>
<data name="WCFResponseReceived" xml:space="preserve">
<value>Resposta do WCF recebida: {0}</value>
<comment>{0} will be replaced by WCF response</comment>
</data>
<data name="WCFSendingCommand" xml:space="preserve">
<value>Enviando o comando: {0} para o servidor WCF no {1}...</value>
<value>Enviando comando: {0} para o servidor WCF em {1}...</value>
<comment>{0} will be replaced by WCF command, {1} will be replaced by WCF hostname</comment>
</data>
<data name="WCFStarting" xml:space="preserve">
<value>Iniciando o servidor WCF em {0}...</value>
<value>Iniciando servidor WCF em {0}...</value>
<comment>{0} will be replaced by WCF hostname</comment>
</data>
<data name="BotAlreadyStopped" xml:space="preserve">
@@ -411,7 +412,7 @@ StackTrace:
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name, {2} will be replaced by translated TimeSpan string built from TimeSpan* translation parts</comment>
</data>
<data name="IdlingFinishedForGames" xml:space="preserve">
<value>Finalizado o processo de receber cartas dos jogos: {0}</value>
<value>Finalizada a coleta de cartas dos jogos: {0}</value>
<comment>{0} will be replaced by list of the games (appIDs, numbers), separated by a comma</comment>
</data>
<data name="IdlingStatusForGame" xml:space="preserve">
@@ -422,7 +423,7 @@ StackTrace:
<value>Coleta de cartas interrompida!</value>
</data>
<data name="IgnoredStickyPauseEnabled" xml:space="preserve">
<value>Ignorando esse pedido, já que o pause manual está habilitado!</value>
<value>Ignorando esse pedido, já que a pausa forçada está habilitada!</value>
</data>
<data name="NothingToIdle" xml:space="preserve">
<value>Não temos cartas disponíveis nesta conta!</value>
@@ -497,7 +498,7 @@ StackTrace:
<comment>{0} will be replaced by generated 2FA token (string)</comment>
</data>
<data name="BotAutomaticIdlingNowPaused" xml:space="preserve">
<value>Processo automático de receber cartas está agora pausado!</value>
<value>A coleta automática de cartas foi pausada!</value>
</data>
<data name="BotAutomaticIdlingNowResumed" xml:space="preserve">
<value>A coleta automática de cartas foi retomada!</value>
@@ -696,4 +697,8 @@ StackTrace:
<value>O ASF tentará usar seu preferido {0} idle, mas a tradução para este idioma foi concluída somente em {1}. Talvez você possa nos ajudar a melhorar a tradução do ASF ao seu idioma?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>A execução de {0} ({1}) está temporariamente desativada, visto que esse jogo não foi lançado ainda.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -692,4 +692,5 @@ inválidas, abortando!</value>
<value>Seu CurrentCulture fornecido é inválido, ASF continuará a funcionar com o predefinido!</value>
</data>
</root>

View File

@@ -697,4 +697,8 @@ StackTrace:
<value>ASF will attempt to use your preferred {0} culture, but translation in that language was completed only in {1}. Perhaps you could help us improve ASF translation for your language?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Idling {0} ({1}) is temporarily disabled, as that game was not released yet.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -697,4 +697,8 @@ StackTrace:
<value>ASF va încerca să utilizeze cultura {0} preferată de tine, dar traducerea în această limbă a fost completată în proporție de {1}. Poate că ai putea ajuta la îmbunatățirea traducerii ASF pentru limba ta?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Farmatul {0} ({1}) este dezactivat temporar, deoarece acest joc nu a fost încă lansat.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -384,7 +384,7 @@
<comment>{0} will be replaced by bot's name, {1} will be replaced by game's appID (number), {2} will be replaced by game's name, {3} will be replaced by number of cards left to idle, {4} will be replaced by total number of games to idle, {5} will be replaced by total number of cards to idle, {6} will be replaced by translated TimeSpan string built from TimeSpan* translation parts</comment>
</data>
<data name="BotStatusIdlingList" xml:space="preserve">
<value>Бот {0} фармит игры: {1}. Всего {2} игр ({3} карт) осталось фармить (займет примерно {4}).</value>
<value>Бот {0} фармит игры: {1}. Всего осталось {2} игр ({3} карт, ~{4} осталось).</value>
<comment>{0} will be replaced by bot's name, {1} will be replaced by list of the games (appIDs, numbers), {2} will be replaced by total number of games to idle, {3} will be replaced by total number of cards to idle, {4} will be replaced by translated TimeSpan string built from TimeSpan* translation parts</comment>
</data>
<data name="CheckingFirstBadgePage" xml:space="preserve">
@@ -697,4 +697,8 @@
<value>ASF будет пытаться использовать выбранный язык {0}, но перевод готов только на {1}. Возможно, Вы могли бы помочь улучшить перевод ASF на данный язык?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Фарм {0} ({1}) временно невозможен, потому что эта игра ещё не вышла.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -697,4 +697,5 @@ StackTrace:
<value>ASF će pokušati da koristi vašu preferiranu {0} "kulturu", ali prevod u taj jezik je samo {1} gotov. Možda bi ste mogli da nam pomogne u prevodu ASF na vaš jezik?</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>
</root>

View File

@@ -290,6 +290,7 @@
</root>

View File

@@ -395,7 +395,7 @@ StackTrace:
<value>Kollar andra märkessidor...</value>
</data>
<data name="ChosenFarmingAlgorithm" xml:space="preserve">
<value>Vald farm algoritm: {0}</value>
<value>Vald farmning algoritm: {0}</value>
<comment>{0} will be replaced by the name of chosen idling algorithm</comment>
</data>
<data name="Done" xml:space="preserve">
@@ -694,5 +694,12 @@ StackTrace:
<data name="ErrorInvalidCurrentCulture" xml:space="preserve">
<value>Din angivna CurrentCulture är ogiltlig, ASF kommer fortsätta köras med standardvärdet!</value>
</data>
<data name="TranslationIncomplete" xml:space="preserve">
<value>ASF kommer försöka att använda din föredragna {0}, men den översättningen är endast {1} färdig. Du kanske kan hjälpa oss att förbättra ASF översättningarna för ditt språk?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Farmning {0} ({1}) är tillfälligt inaktiverad, då spelet inte är släppt ännu.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -278,6 +278,7 @@
</root>

View File

@@ -693,5 +693,12 @@ Hata bilgileri:
<data name="ErrorInvalidCurrentCulture" xml:space="preserve">
<value>Sağlanan CurrentCulture geçersiz, ASF varsayılan ile çalışmaya devam edecek!</value>
</data>
<data name="TranslationIncomplete" xml:space="preserve">
<value>ASF tercih ettiğiniz {0} kültürünü kullanmaya çalışacak, ancak o dildeki çeviri yalnızca {1} içinde tamamlandı. Diliniz için ASF çevirisini geliştirmemize belki de yardımcı olabilir misiniz?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Rölantide {0} ({1}) geçici olarak devre dışı bırakıldı, Bu oyun henüz çıkış yapmadı.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -566,10 +566,10 @@
<value>Обмін надісланий!</value>
</data>
<data name="BotLootingTemporarilyDisabled" xml:space="preserve">
<value>Лутінг тимчасово відключений!</value>
<value>Збір предметів тимчасово відключений!</value>
</data>
<data name="BotLootingYourself" xml:space="preserve">
<value>Ви не можете лутати себе!</value>
<value>Неможливо збирати предмети з самого себе!</value>
</data>
<data name="BotNoASFAuthenticator" xml:space="preserve">
<value>Цей бот не має включеного ASF 2FA! Забули імпортувати автентифікатор у ASF 2FA?</value>
@@ -609,7 +609,7 @@
<comment>{0} will be replaced by bot's name</comment>
</data>
<data name="BotStatusLimited" xml:space="preserve">
<value>Бот {0} має обмеження і не може ідліти карти.</value>
<value>Бот {0} має обмеження і не може отримувати карти.</value>
<comment>{0} will be replaced by bot's name</comment>
</data>
<data name="BotStatusNotConnected" xml:space="preserve">
@@ -652,13 +652,13 @@
<value>Підключення до мережі Steam втрачено, повторне підключення...</value>
</data>
<data name="BotAccountFree" xml:space="preserve">
<value>Аккаунт більше не зайнятий, іділінг відновлено!</value>
<value>Аккаунт більше не зайнятий, роботу відновлено!</value>
</data>
<data name="BotAccountOccupied" xml:space="preserve">
<value>Акаунт зараз використовується, ASF продовжить коли аккаунт звільниться...</value>
</data>
<data name="BotAutomaticIdlingPauseTimeout" xml:space="preserve">
<value>Сімейна бібліотека не була запущена у відведений період часу, фарм відновлено!</value>
<value>Сімейна бібліотека не була запущена у відведений період часу, роботу відновлено!</value>
</data>
<data name="BotConnecting" xml:space="preserve">
<value>Підключення...</value>
@@ -697,4 +697,8 @@
<value>ASF намагатиметься використовувати обрану мову {0}, але переклад на цю мову завершено лише на {1}. Можливо ви б змогли допомогти в перекладі ASF вашою мовою?</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>Обробка {0} ({1}) тимчасово неможлива, тому що ця гра ще не була випущена.</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -697,4 +697,5 @@ StackTrace:
<value>ASF sẽ cố gắng sử dụng mã ngôn ngữ {0} ưa thích của bạn, nhưng bản dịch ngôn ngữ đó hoàn thiện chỉ được {1}. Có lẽ bạn có thể giúp chúng tôi cải thiện bản dịch ASF cho ngôn ngữ của bạn?</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>
</root>

View File

@@ -694,4 +694,8 @@
<value>ASF将尝试使用您偏好的语言{0},但该语言当前的翻译完成度为{1}。或许你可以帮助我们改进ASF的翻译</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>{0} ({1}) 的挂卡暂时不可用,因为该游戏尚未发布。</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -694,4 +694,8 @@
<value>ASF 將使用您的偏好語系 {0} ,但該語言的翻譯只完成了 {1}。請協助我們改進 ASF 的翻譯品質。</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="IdlingGameNotReleasedYet" xml:space="preserve">
<value>掛卡 {0} ({1}) 已暫時停止,因為該遊戲尚未發行。</value>
<comment>{0} will be replaced by game's appID (number), {1} will be replaced by game's name</comment>
</data>
</root>

View File

@@ -52,12 +52,12 @@ namespace ArchiSteamFarm {
private static bool ShutdownSequenceInitialized;
internal static void Exit(byte exitCode = 0) {
internal static async Task Exit(byte exitCode = 0) {
if (exitCode != 0) {
ASF.ArchiLogger.LogGenericError(Strings.ErrorExitingWithNonZeroErrorCode);
}
Shutdown();
await Shutdown().ConfigureAwait(false);
Environment.Exit(exitCode);
}
@@ -114,8 +114,8 @@ namespace ArchiSteamFarm {
return !string.IsNullOrEmpty(result) ? result.Trim() : null;
}
internal static void Restart() {
if (!InitShutdownSequence()) {
internal static async Task Restart() {
if (!await InitShutdownSequence().ConfigureAwait(false)) {
return;
}
@@ -168,13 +168,15 @@ namespace ArchiSteamFarm {
Logging.InitLoggers();
ASF.ArchiLogger.LogGenericInfo("ASF V" + SharedInfo.Version);
await InitServices().ConfigureAwait(false);
await InitGlobalConfigAndLanguage().ConfigureAwait(false);
if (!Runtime.IsRuntimeSupported) {
ASF.ArchiLogger.LogGenericError(Strings.WarningRuntimeUnsupported);
await Task.Delay(10 * 1000).ConfigureAwait(false);
await Task.Delay(60 * 1000).ConfigureAwait(false);
}
await InitGlobalDatabaseAndServices().ConfigureAwait(false);
// If debugging is on, we prepare debug directory prior to running
if (GlobalConfig.Debug) {
if (Directory.Exists(SharedInfo.DebugDirectory)) {
@@ -199,7 +201,7 @@ namespace ArchiSteamFarm {
// If we ran ASF as a client, we're done by now
if (Mode.HasFlag(EMode.Client) && !Mode.HasFlag(EMode.Server)) {
Exit();
await Exit().ConfigureAwait(false);
}
await ASF.CheckForUpdate().ConfigureAwait(false);
@@ -207,14 +209,14 @@ namespace ArchiSteamFarm {
ASF.InitFileWatcher();
}
private static async Task InitServices() {
private static async Task InitGlobalConfigAndLanguage() {
string globalConfigFile = Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalConfigFileName);
GlobalConfig = GlobalConfig.Load(globalConfigFile);
if (GlobalConfig == null) {
ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorGlobalConfigNotLoaded, globalConfigFile));
await Task.Delay(5 * 1000).ConfigureAwait(false);
Exit(1);
await Exit(1).ConfigureAwait(false);
return;
}
@@ -229,13 +231,12 @@ namespace ArchiSteamFarm {
}
int defaultResourceSetCount = 0;
int currentResourceSetCount = 0;
ResourceSet defaultResourceSet = Strings.ResourceManager.GetResourceSet(CultureInfo.CreateSpecificCulture("en-US"), true, true);
ResourceSet defaultResourceSet = Strings.ResourceManager.GetResourceSet(CultureInfo.GetCultureInfo("en-US"), true, true);
if (defaultResourceSet != null) {
defaultResourceSetCount = defaultResourceSet.Cast<object>().Count();
}
int currentResourceSetCount = 0;
ResourceSet currentResourceSet = Strings.ResourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, false);
if (currentResourceSet != null) {
currentResourceSetCount = currentResourceSet.Cast<object>().Count();
@@ -245,7 +246,9 @@ namespace ArchiSteamFarm {
float translationCompleteness = currentResourceSetCount / (float) defaultResourceSetCount;
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.TranslationIncomplete, CultureInfo.CurrentCulture.Name, translationCompleteness.ToString("P1")));
}
}
private static async Task InitGlobalDatabaseAndServices() {
string globalDatabaseFile = Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalDatabaseFileName);
if (!File.Exists(globalDatabaseFile)) {
@@ -258,7 +261,7 @@ namespace ArchiSteamFarm {
if (GlobalDatabase == null) {
ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorDatabaseInvalid, globalDatabaseFile));
await Task.Delay(5 * 1000).ConfigureAwait(false);
Exit(1);
await Exit(1).ConfigureAwait(false);
return;
}
@@ -269,7 +272,7 @@ namespace ArchiSteamFarm {
WebBrowser = new WebBrowser(ASF.ArchiLogger);
}
private static bool InitShutdownSequence() {
private static async Task<bool> InitShutdownSequence() {
if (ShutdownSequenceInitialized) {
return false;
}
@@ -277,9 +280,9 @@ namespace ArchiSteamFarm {
ShutdownSequenceInitialized = true;
WCF.StopServer();
foreach (Bot bot in Bot.Bots.Values) {
bot.Stop();
}
IEnumerable<Task> tasks = Bot.Bots.Values.Select(bot => Task.Run(() => bot.Stop()));
await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(10 * 1000));
return true;
}
@@ -293,7 +296,7 @@ namespace ArchiSteamFarm {
ShutdownResetEvent.Wait();
// We got a signal to shutdown
Exit();
Exit().Wait();
} else {
// Service
IsRunningAsService = true;
@@ -371,22 +374,23 @@ namespace ArchiSteamFarm {
}
}
private static void Shutdown() {
if (!InitShutdownSequence()) {
private static async Task Shutdown() {
if (!await InitShutdownSequence().ConfigureAwait(false)) {
return;
}
ShutdownResetEvent.Set();
}
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) {
private static async void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) {
if (args?.ExceptionObject == null) {
ASF.ArchiLogger.LogNullError(nameof(args) + " || " + nameof(args.ExceptionObject));
return;
}
ASF.ArchiLogger.LogFatalException((Exception) args.ExceptionObject);
Exit(1);
await Task.Delay(5000).ConfigureAwait(false);
await Exit(1).ConfigureAwait(false);
}
private static void UnobservedTaskExceptionHandler(object sender, UnobservedTaskExceptionEventArgs args) {
@@ -396,7 +400,8 @@ namespace ArchiSteamFarm {
}
ASF.ArchiLogger.LogFatalException(args.Exception);
Exit(1);
// Normally we should abort the application here, but many tasks are in fact failing in SK2 code which we can't easily fix
// Thanks Valve.
}
[Flags]
@@ -422,7 +427,7 @@ namespace ArchiSteamFarm {
Stop();
});
protected override void OnStop() => Shutdown();
protected override async void OnStop() => await Shutdown().ConfigureAwait(false);
}
}
}

View File

@@ -44,7 +44,7 @@ namespace ArchiSteamFarm {
internal const string ServiceDescription = "ASF is an application that allows you to farm steam cards using multiple steam accounts simultaneously.";
internal const string ServiceName = "ArchiSteamFarm";
internal const string StatisticsServer = "asf.justarchi.net";
internal const string VersionNumber = "2.2.1.8";
internal const string VersionNumber = "2.2.2.4";
internal static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version;
}

View File

@@ -192,7 +192,7 @@ namespace ArchiSteamFarm {
// If it's steam fuckup, temporarily ignore it, otherwise react accordingly, depending on our preference
if (tradeOffer.ItemsToReceive.Count == 0) {
donationResult = ParseTradeResult.EResult.RejectedTemporarily;
} else if (Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.AcceptDonations) || ((tradeOffer.OtherSteamID64 != 0) && Bot.Bots.Values.Any(bot => bot.SteamID == tradeOffer.OtherSteamID64))) {
} else if (Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.AcceptDonations) || (!Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.DontAcceptBotTrades) && (tradeOffer.OtherSteamID64 != 0) && Bot.Bots.Values.Any(bot => bot.SteamID == tradeOffer.OtherSteamID64))) {
donationResult = ParseTradeResult.EResult.AcceptedWithoutItemLose;
} else {
donationResult = ParseTradeResult.EResult.RejectedPermanently;

View File

@@ -39,8 +39,6 @@ namespace ArchiSteamFarm {
}
internal sealed class WCF : IWCF, IDisposable {
private static string URL = "net.tcp://127.0.0.1:1242/ASF";
internal bool IsServerRunning => ServiceHost != null;
private Client Client;
@@ -81,12 +79,7 @@ namespace ArchiSteamFarm {
internal static void Init() {
if (string.IsNullOrEmpty(Program.GlobalConfig.WCFHost)) {
Program.GlobalConfig.WCFHost = Program.GetUserInput(ASF.EUserInputType.WCFHostname);
if (string.IsNullOrEmpty(Program.GlobalConfig.WCFHost)) {
return;
}
}
URL = "net.tcp://" + Program.GlobalConfig.WCFHost + ":" + Program.GlobalConfig.WCFPort + "/ASF";
}
internal string SendCommand(string input) {
@@ -95,17 +88,24 @@ namespace ArchiSteamFarm {
return null;
}
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.WCFSendingCommand, input, URL));
Binding binding = GetTargetBinding();
if (binding == null) {
ASF.ArchiLogger.LogNullError(nameof(binding));
return null;
}
string url = GetUrlFromBinding(binding);
if (string.IsNullOrEmpty(url)) {
ASF.ArchiLogger.LogNullError(nameof(url));
return null;
}
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.WCFSendingCommand, input, url));
if (Client == null) {
Client = new Client(
new NetTcpBinding {
// We use SecurityMode.None for Mono compatibility
// Yes, also on Windows, for Mono<->Windows communication
Security = { Mode = SecurityMode.None },
SendTimeout = new TimeSpan(0, 0, Program.GlobalConfig.ConnectionTimeout)
},
new EndpointAddress(URL)
binding,
new EndpointAddress(url)
);
}
@@ -117,20 +117,28 @@ namespace ArchiSteamFarm {
return;
}
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.WCFStarting, URL));
Binding binding = GetTargetBinding();
if (binding == null) {
ASF.ArchiLogger.LogNullError(nameof(binding));
return;
}
string url = GetUrlFromBinding(binding);
if (string.IsNullOrEmpty(url)) {
ASF.ArchiLogger.LogNullError(nameof(url));
return;
}
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.WCFStarting, url));
try {
ServiceHost = new ServiceHost(typeof(WCF), new Uri(URL));
ServiceHost = new ServiceHost(typeof(WCF), new Uri(url));
ServiceHost.AddServiceEndpoint(
typeof(IWCF),
new NetTcpBinding {
// We use SecurityMode.None for Mono compatibility
// Yes, also on Windows, for Mono<->Windows communication
Security = { Mode = SecurityMode.None },
SendTimeout = new TimeSpan(0, 0, Program.GlobalConfig.ConnectionTimeout)
},
binding,
string.Empty
);
ServiceHost.Open();
ASF.ArchiLogger.LogGenericInfo(Strings.WCFReady);
@@ -157,6 +165,46 @@ namespace ArchiSteamFarm {
ServiceHost = null;
}
private static Binding GetTargetBinding() {
Binding result;
switch (Program.GlobalConfig.WCFBinding) {
case GlobalConfig.EWCFBinding.NetTcp:
result = new NetTcpBinding {
// We use SecurityMode.None for Mono compatibility
// Yes, also on Windows, for Mono<->Windows communication
Security = { Mode = SecurityMode.None }
};
break;
case GlobalConfig.EWCFBinding.BasicHttp:
result = new BasicHttpBinding();
break;
case GlobalConfig.EWCFBinding.WSHttp:
result = new WSHttpBinding {
// We use SecurityMode.None for Mono compatibility
// Yes, also on Windows, for Mono<->Windows communication
Security = { Mode = SecurityMode.None }
};
break;
default:
ASF.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(Program.GlobalConfig.WCFBinding), Program.GlobalConfig.WCFBinding));
goto case GlobalConfig.EWCFBinding.NetTcp;
}
result.SendTimeout = new TimeSpan(0, 0, Program.GlobalConfig.ConnectionTimeout);
return result;
}
private static string GetUrlFromBinding(Binding binding) {
if (binding != null) {
return binding.Scheme + "://" + Program.GlobalConfig.WCFHost + ":" + Program.GlobalConfig.WCFPort + "/ASF";
}
ASF.ArchiLogger.LogNullError(nameof(binding));
return null;
}
private void StopClient() {
if (Client == null) {
return;

View File

@@ -81,7 +81,7 @@ namespace ArchiSteamFarm {
// Therefore, call mono-incompatible options in their own function to avoid that, and just leave the function call here
// When compiling on Mono, this section is omitted entirely as we never run Mono-compiled ASF on Windows
// Moreover, Mono compiler doesn't even include ReusePort field in ServicePointManager, so it's crucial to avoid compilation error
if (Runtime.IsRuntimeSupported && !Runtime.IsRunningOnMono) {
if (!Runtime.IsRunningOnMono) {
InitNonMonoBehaviour();
}
#endif

View File

@@ -26,6 +26,7 @@
"SteamOwnerID": 0,
"SteamProtocol": 6,
"UpdateChannel": 1,
"WCFBinding": 0,
"WCFHost": "127.0.0.1",
"WCFPort": 1242
}

View File

@@ -28,5 +28,5 @@
"SteamParentalPIN": "0",
"SteamPassword": null,
"SteamTradeToken": null,
"TradingPreferences": 1
"TradingPreferences": 0
}

View File

@@ -136,7 +136,7 @@ namespace ConfigGenerator {
[LocalizedCategory("Advanced")]
[Editor(typeof(FlagEnumUiEditor), typeof(UITypeEditor))]
[JsonProperty(Required = Required.DisallowNull)]
public ETradingPreferences TradingPreferences { get; set; } = ETradingPreferences.AcceptDonations;
public ETradingPreferences TradingPreferences { get; set; } = ETradingPreferences.None;
[SuppressMessage("ReSharper", "UnusedMember.Local")]
private BotConfig() { }
@@ -207,7 +207,8 @@ namespace ConfigGenerator {
None = 0,
AcceptDonations = 1,
SteamTradeMatcher = 2,
MatchEverything = 4
MatchEverything = 4,
DontAcceptBotTrades = 8
}
}
}

View File

@@ -117,6 +117,10 @@ namespace ConfigGenerator {
[JsonProperty(Required = Required.DisallowNull)]
public EUpdateChannel UpdateChannel { get; set; } = EUpdateChannel.Stable;
[LocalizedCategory("Access")]
[JsonProperty(Required = Required.DisallowNull)]
public EWCFBinding WCFBinding { get; set; } = EWCFBinding.NetTcp;
[LocalizedCategory("Access")]
[JsonProperty]
public string WCFHost { get; set; } = "127.0.0.1";
@@ -220,5 +224,11 @@ namespace ConfigGenerator {
Stable,
Experimental
}
internal enum EWCFBinding : byte {
NetTcp,
BasicHttp,
WSHttp
}
}
}

View File

@@ -117,28 +117,82 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CategoryAccess" xml:space="preserve">
<value>Достъп</value>
</data>
<data name="CategoryAdvanced" xml:space="preserve">
<value>Разширени настройки</value>
</data>
<data name="CategoryCore" xml:space="preserve">
<value>Основни</value>
</data>
<data name="CategoryDebugging" xml:space="preserve">
<value>Отстраняване на грешки</value>
</data>
<data name="CategoryPerformance" xml:space="preserve">
<value>Производителност</value>
</data>
<data name="CategoryUpdates" xml:space="preserve">
<value>Обновления</value>
</data>
<data name="ConfirmRemoval" xml:space="preserve">
<value>Наистина ли искате да премахнете тези настройки?</value>
</data>
<data name="ErrorBotNameEmpty" xml:space="preserve">
<value>Не сте задали име на бота!</value>
</data>
<data name="ErrorCantRemoveGlobalConfig" xml:space="preserve">
<value>Не можете да премахнете общите настройки!</value>
</data>
<data name="ErrorCantRenameGlobalConfig" xml:space="preserve">
<value>Не можете да преименувате общите настройки!</value>
</data>
<data name="ErrorConfigDirectoryNotFound" xml:space="preserve">
<value>Папката с настройките не може да бъде открита!</value>
</data>
<data name="ErrorConfigPropertyInvalid" xml:space="preserve">
<value>Конфигурираното свойство {0} е невалидно: {1}</value>
<comment>{0} will be replaced by name of the configuration property, {1} will be replaced by invalid value</comment>
</data>
<data name="ErrorInvalidCurrentCulture" xml:space="preserve">
<value>Задали сте невалиден CurrentCulture. ConfigGenerator ще продължи работа със зададения по подразбиране!</value>
</data>
<data name="ErrorNameAlreadyUsed" xml:space="preserve">
<value>Потребителското име вече използвано!</value>
<comment>This happens e.g. when user wants to create a bot with name that exists already</comment>
</data>
<data name="ErrorNameReserved" xml:space="preserve">
<value>Това име е вече запазено!</value>
<comment>This happens e.g. when user wants to create a bot with reserved name, such as "ASF"</comment>
</data>
<data name="ErrorObjectIsNull" xml:space="preserve">
<value>{0} е нулев!</value>
<comment>{0} will be replaced by object's name</comment>
</data>
<data name="ErrorVersionMismatch" xml:space="preserve">
<value>Опитахте се да ползвате невалидна версия на ConfigGenerator, за вашия ASF!
ASF: {0} | ConfigGenerator: {1}
Моля ползвайте ConfigGenerator със съответсваща версия на вашия ASF! Ще бъдете пренасочен към съответващата версия...</value>
<comment>{0} will be replaced by ASF version (string), {1} will be replaced by ConfigGenerator version (string). Please note that this string should include newlines for formatting.</comment>
</data>
<data name="New" xml:space="preserve">
<value>Ново</value>
<comment>This is used as MessageBox title</comment>
</data>
<data name="Removal" xml:space="preserve">
<value>Премахване</value>
<comment>This is used as MessageBox title</comment>
</data>
<data name="Rename" xml:space="preserve">
<value>Преименуване</value>
<comment>This is used as MessageBox title</comment>
</data>
<data name="TutorialBotFormEnabled" xml:space="preserve">
<value>Чудесно! Вече твоят бот е в готовност. Всъщност, това бе всичко, което ти трябваше да изпълниш, за да ползваш този бот в ASF, но все пак, може да поискаш да зададеш поне още 2 възможности: {0} и {1}. Ако искаш да продължиш с обучението, моля, заповявай. Не забравяй да се обърнеш към wiki ако не си сигурен, как различните настройки да бъдат зададени или ако искаш допълнителна помощ.</value>
<comment>{0} will be replaced by "SteamLogin" configuration property, {1} will be replaced by "SteamPassword" configuration property</comment>
</data>
@@ -150,11 +204,12 @@
<data name="UserInputBotName" xml:space="preserve">
<value>Моля, въведете ново име за бот: </value>
<comment>Please note that this translation should end with space</comment>
</data>
<data name="WarningConfigPropertyModified" xml:space="preserve">
<value>{0} бе зададено на: {1}</value>
<comment>{0} will be replaced by name of the configuration property, {1} will be replaced by new value</comment>
</data>
</root>

View File

@@ -123,32 +123,92 @@
<data name="ConfirmRemoval" xml:space="preserve">
<value>Haluatko varmasti poistaa tämän config tiedoston?</value>
</data>
<data name="ErrorBotNameEmpty" xml:space="preserve">
<value>Botin nimi on tyhjä!</value>
</data>
<data name="ErrorCantRemoveGlobalConfig" xml:space="preserve">
<value>Et voi poistaa global config tiedostoa!</value>
</data>
<data name="ErrorCantRenameGlobalConfig" xml:space="preserve">
<value>Et voi uudelleennimetä global config tiedostoa!</value>
</data>
<data name="ErrorConfigDirectoryNotFound" xml:space="preserve">
<value>Config kansiota ei löytynyt!</value>
</data>
<data name="ErrorConfigPropertyInvalid" xml:space="preserve">
<value>Kohdassa {0} muokattu arvo {1} on epäkelpo.</value>
<comment>{0} will be replaced by name of the configuration property, {1} will be replaced by invalid value</comment>
</data>
<data name="ErrorInvalidCurrentCulture" xml:space="preserve">
<value>Antamasi/syöttämäsi CurrentCulture on epäkelpo, ConfigGenerator jatkaa toimintaa oletusarvolla!</value>
</data>
<data name="ErrorNameAlreadyUsed" xml:space="preserve">
<value>Tämä nimi on jo käytössä!</value>
<comment>This happens e.g. when user wants to create a bot with name that exists already</comment>
</data>
<data name="ErrorNameReserved" xml:space="preserve">
<value>Tämä nimi on jo käytössä!</value>
<comment>This happens e.g. when user wants to create a bot with reserved name, such as "ASF"</comment>
</data>
<data name="ErrorVersionMismatch" xml:space="preserve">
<value>Yritit käyttää epäsopivaa ConfigGenerator versiota ASF :lläsi!
ASF: {0} | ConfigGenerator: {1}
Käytä yhteensopivaa ConfigGenerator versiota ASF binäärillesi. Sinut ohjataan oikean julkaisun sivulle...</value>
<comment>{0} will be replaced by ASF version (string), {1} will be replaced by ConfigGenerator version (string). Please note that this string should include newlines for formatting.</comment>
</data>
<data name="New" xml:space="preserve">
<value>Uusi</value>
<comment>This is used as MessageBox title</comment>
</data>
<data name="Removal" xml:space="preserve">
<value>Poistaminen</value>
<comment>This is used as MessageBox title</comment>
</data>
<data name="Rename" xml:space="preserve">
<value>Nimeä uudelleen</value>
<comment>This is used as MessageBox title</comment>
</data>
<data name="TutorialBotFormReady" xml:space="preserve">
<value>ASF on nyt valmis! Käynnistä ASF.exe binääri ja jos syötit kaikki tiedot oikein, pitäisi sinun huomata että ASF kirjautuu sisään ja aloittaa idlaamisen. Jos sinulla on SteamGuard tai kaksivaiheinen todennus käytössä, saattaa ASF joutua kysymään sinulta valtuuksia noita käyttäjiä varten.</value>
</data>
<data name="TutorialMainFormBotsManagementButtons" xml:space="preserve">
<value>Ikkunan yläosassa voit huomata tällä hetkellä ladatun configin ja 3 extra painiketta, poistamiselle [-], uudelleennimeämiselle [~] ja uusien lisäämiselle [+].</value>
<comment>If possible, try to keep visual representation of buttons: [-], [~] and [+]</comment>
</data>
<data name="TutorialMainFormFinished" xml:space="preserve">
<value>Okei. Aloitetaan konfiguroimaan meidän ASF :ää. Paina plus-painiketta [+] lisätäksesi ensimmäinen steam accountisi!</value>
<comment>If possible, try to keep visual representation of [+] button</comment>
</data>
<data name="TutorialMainFormHelpButton" xml:space="preserve">
<value>Oikeasta yläkulmasta löytyy apua-painike [?] joka ohjaa sinut ASF wikiin lisätiedon saamiseksi.</value>
<comment>If possible, try to keep visual representation of [?] button</comment>
</data>
<data name="TutorialMainFormShown" xml:space="preserve">
<value>Tämä on ASF ConfigGeneratorin pääikkuna, se on todella helppo käyttää!</value>
</data>
<data name="TutorialNewBotFormFinished" xml:space="preserve">
<value>Kuten näet, sinun bottisi on nyt valmiina muokattavaksi! Ensimmäinen asia jonka haluat tehdä on muuttaa kohdasta {0} arvo false to true, kokeile!</value>
<comment>{0} will be replaced by name of the configuration property ("Enabled")</comment>
</data>
<data name="TutorialNewBotFormShown" xml:space="preserve">
<value>Hienoa! Nyt sinua pyydetään nimeämään bottisi. Hyvä esimerkki on nimetä se steam accountin mukaan jota aiot konfiguroida. Mikä tahansa muukin nimi käy, kunhan se on sinulle helposti yhdistettävissä samaan botti-instanssiin jota aiot konfiguroida.</value>
</data>
<data name="TutorialStart" xml:space="preserve">
<value>Tervetuloa! Huomasin, että käytät ASF ConfigGeneratoria ensimmäistä kertaa, anna minun auttaa sinut alkuun.</value>
</data>
<data name="UserInputBotName" xml:space="preserve">
<value>Anna uudelle botillesi nimi: </value>
<comment>Please note that this translation should end with space</comment>
</data>
</root>

View File

@@ -121,7 +121,7 @@
<value>Toegang</value>
</data>
<data name="CategoryAdvanced" xml:space="preserve">
<value>Geadvanceerd</value>
<value>Geavanceerd</value>
</data>
<data name="CategoryCore" xml:space="preserve">
<value>Kern</value>
@@ -145,10 +145,10 @@
<value>Je kan het globale config bestand niet verwijderen!</value>
</data>
<data name="ErrorCantRenameGlobalConfig" xml:space="preserve">
<value>Je kan het het globale config bestand niet verwijderen!</value>
<value>Je kan het globale config bestand niet hernoemen!</value>
</data>
<data name="ErrorConfigDirectoryNotFound" xml:space="preserve">
<value>Configuratie folder kon niet gevonden worden!</value>
<value>Configuratiefolder kon niet gevonden worden!</value>
</data>
<data name="ErrorConfigPropertyInvalid" xml:space="preserve">
<value>Geconfigureerde {0} eigenschap is ongeldig: {1}</value>
@@ -158,7 +158,7 @@
<value>De opgegeven CurrentCulture is ongeldig, ConfigGenerator blijft draaien met de standaard!</value>
</data>
<data name="ErrorNameAlreadyUsed" xml:space="preserve">
<value>Deze naam is al in gebruik!</value>
<value>Deze naam is al gebruikt!</value>
<comment>This happens e.g. when user wants to create a bot with name that exists already</comment>
</data>
<data name="ErrorNameReserved" xml:space="preserve">
@@ -229,7 +229,7 @@ Je kan, als je wilt, doorgaan met deze tutorial. Vergeet niet de wiki te gebruik
<value>Goed gedaan! Je wordt nu gevraagd voor een naam voor je bot. Een goede voorbeeld is de nickname die je voor je Steam account gebruikt. Of elk ander naam die makkelijk voor jou is om te herinneren om welke bot het gaat.</value>
</data>
<data name="TutorialStart" xml:space="preserve">
<value>Welkom! Ik zie dat dit de eerste keer is dat ASF ConfigGenerator gebruikt, laat me je daar een beetje mee helpen.</value>
<value>Welkom! Ik zie dat dit de eerste keer is dat je ASF ConfigGenerator gebruikt, laat me je daar een beetje mee helpen.</value>
</data>
<data name="UserInputBotName" xml:space="preserve">
<value>Voer een nieuwe naam in voor de bot: </value>

View File

@@ -118,10 +118,10 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CategoryAccess" xml:space="preserve">
<value>Erişim</value>
<value>Erişim İzni</value>
</data>
<data name="CategoryAdvanced" xml:space="preserve">
<value>Gelişmiş</value>
<value>İleri düzey</value>
</data>
<data name="CategoryCore" xml:space="preserve">
<value>Temel</value>

View File

@@ -59,7 +59,7 @@ namespace ArchiSteamFarm {
BotStatusForm.BotForms[PreviouslySelectedBotName].Visible = true;
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e) => Program.InitShutdownSequence();
private async void MainForm_FormClosed(object sender, FormClosedEventArgs e) => await Program.InitShutdownSequence().ConfigureAwait(false);
private async void MainForm_Load(object sender, EventArgs e) {
Logging.InitFormLogger();

View File

@@ -1,11 +1,12 @@
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ArchiSteamFarm.Localization;
using SteamKit2;
namespace ArchiSteamFarm {
@@ -16,8 +17,14 @@ namespace ArchiSteamFarm {
internal static GlobalDatabase GlobalDatabase { get; private set; }
internal static WebBrowser WebBrowser { get; private set; }
internal static void Exit(int exitCode = 0) {
InitShutdownSequence();
private static bool ShutdownSequenceInitialized;
internal static async Task Exit(byte exitCode = 0) {
if (exitCode != 0) {
ASF.ArchiLogger.LogGenericError(Strings.ErrorExitingWithNonZeroErrorCode);
}
await Shutdown().ConfigureAwait(false);
Environment.Exit(exitCode);
}
@@ -25,25 +32,28 @@ namespace ArchiSteamFarm {
return null; // TODO
}
internal static void InitShutdownSequence() {
foreach (Bot bot in Bot.Bots.Values.Where(bot => bot.KeepRunning)) {
bot.Stop();
}
}
internal static void Restart() {
InitShutdownSequence();
try {
Process.Start(Assembly.GetEntryAssembly().Location, string.Join(" ", Environment.GetCommandLineArgs().Skip(1)));
} catch (Exception e) {
ArchiLogger.LogGenericException(e);
internal static async Task<bool> InitShutdownSequence() {
if (ShutdownSequenceInitialized) {
return false;
}
Environment.Exit(0);
ShutdownSequenceInitialized = true;
IEnumerable<Task> tasks = Bot.Bots.Values.Select(bot => Task.Run(() => bot.Stop()));
await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(10 * 1000));
return true;
}
private static void Init() {
internal static async Task Restart() {
if (!await InitShutdownSequence().ConfigureAwait(false)) {
return;
}
Application.Restart();
}
private static async Task Init() {
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
TaskScheduler.UnobservedTaskException += UnobservedTaskExceptionHandler;
@@ -77,7 +87,7 @@ namespace ArchiSteamFarm {
}
}
InitServices();
await InitServices().ConfigureAwait(false);
// If debugging is on, we prepare debug directory prior to running
if (GlobalConfig.Debug) {
@@ -95,13 +105,13 @@ namespace ArchiSteamFarm {
Logging.InitEnhancedLoggers();
}
private static void InitServices() {
private static async Task InitServices() {
string globalConfigFile = Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalConfigFileName);
GlobalConfig = GlobalConfig.Load(globalConfigFile);
if (GlobalConfig == null) {
ArchiLogger.LogGenericError("Global config could not be loaded, please make sure that " + globalConfigFile + " exists and is valid!");
Exit(1);
await Exit(1).ConfigureAwait(false);
}
string globalDatabaseFile = Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalDatabaseFileName);
@@ -109,7 +119,7 @@ namespace ArchiSteamFarm {
GlobalDatabase = GlobalDatabase.Load(globalDatabaseFile);
if (GlobalDatabase == null) {
ArchiLogger.LogGenericError("Global database could not be loaded, if issue persists, please remove " + globalDatabaseFile + " in order to recreate database!");
Exit(1);
await Exit(1).ConfigureAwait(false);
}
ArchiWebHandler.Init();
@@ -123,19 +133,29 @@ namespace ArchiSteamFarm {
/// </summary>
[STAThread]
private static void Main() {
Init();
Init().Wait();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) {
private static async Task Shutdown() {
if (!await InitShutdownSequence().ConfigureAwait(false)) {
return;
}
Application.Exit();
}
private static async void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) {
if (args?.ExceptionObject == null) {
ArchiLogger.LogNullError(nameof(args) + " || " + nameof(args.ExceptionObject));
return;
}
ArchiLogger.LogFatalException((Exception) args.ExceptionObject);
await Task.Delay(5000).ConfigureAwait(false);
await Exit(1).ConfigureAwait(false);
}
private static void UnobservedTaskExceptionHandler(object sender, UnobservedTaskExceptionEventArgs args) {
@@ -145,6 +165,8 @@ namespace ArchiSteamFarm {
}
ArchiLogger.LogFatalException(args.Exception);
// Normally we should abort the application here, but many tasks are in fact failing in SK2 code which we can't easily fix
// Thanks Valve.
}
}
}