nicohman / wyvern Goto Github PK
View Code? Open in Web Editor NEWA simple CLI client for installing and maintaining linux GOG games
License: GNU General Public License v3.0
A simple CLI client for installing and maintaining linux GOG games
License: GNU General Public License v3.0
Installing the Windows versions of the following games fails:
and probably more.
Installing some other games works, such as:
Log output on failure:
name = 'wyvern'
operating_system = 'unix:Arch'
crate_version = '1.4.1'
explanation = '''
Panic occurred in file '~/.cargo/registry/src/github.com-1ecc6299db9ec823/gog-0.4.0/src/extract.rs' at line 243
cause = 'called `Result::unwrap()` on an `Err` value: FromUtf8Error { bytes : [ <removed giant array of integers for brevity> ] }
method = 'Panic'
backtrace = '''
0: 0x5614e4241c63 - <unresolved>
1: 0x5614e3e1eb50 - <unresolved>
2: 0x5614e3dfd591 - <unresolved>
3: 0x5614e3d99726 - <unresolved>
4: 0x5614e3d97f8f - <unresolved>
5: 0x5614e3deb9e3 - <unresolved>
6: 0x5614e3debef3 - <unresolved>
7: 0x5614e421f76e - <unresolved>
8: 0x5614e3d9fea2 - <unresolved>
9: 0x7fb4ff402152 - __libc_start_main
10: 0x5614e3d7c10e - <unresolved>
11: 0x0 - <unresolved>'''
Looks like some kind of an encoding issue perhaps?
Because I wanted to see what error message I got I altered the refresh_token and got the following error. Exit code 101,
It asked to file a bug report, so here it is.
I am guessing it should rather detect that he login information is not valid, and ask you to login again?
Well, this is embarrassing.
wyvern had a problem and crashed. To help us diagnose the problem you can send us a crash report.
We have generated a report file at "/tmp/report-a20b3f83-f898-4b04-9992-87539dcec20f.toml". Submit an issue or email with the subject of "wyvern Crash Report" and include the report as an attachment.
- Authors: nicohman <[email protected]>
We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports.
Thank you kindly!
Crash report
name = 'wyvern'
operating_system = 'unix:Unknown'
crate_version = '1.2.0'
explanation = '''
Panic occurred in file 'src/libcore/result.rs' at line 1009
'''
method = 'Panic'
backtrace = '''
stack backtrace:
0: <no info> (0x55ff3e3723b6)
1: <no info> (0x55ff3e371387)
2: <no info> (0x55ff3e3712ad)
3: <no info> (0x55ff3e2c9ca2)
4: <no info> (0x55ff3e2c9187)
5: <no info> (0x55ff3dfbcecb)
6: <no info> (0x55ff3e3e21e9)
7: <no info> (0x55ff3e3e1ca1)
8: <no info> (0x55ff3e3e1b85)
9: <no info> (0x55ff3e41449c)
10: <no info> (0x55ff3dfe3c79)
11: <no info> (0x55ff3dfb4dfb)
12: <no info> (0x55ff3dfbe4ef)
13: <no info> (0x55ff3e3e1b22)
14: <no info> (0x55ff3e4064d9)
15: <no info> (0x55ff3e3ee85a)
16: <no info> (0x55ff3dfbcf44)
17: <no info> (0x7fd72b670412)
18: <no info> (0x55ff3dfaa15d)
19: <no info> (0x0)'''
The guy over at innoextract says that the installers that wyvern fetches are galaxy installers, and they are more different from normal innosetup files.
Can you see both in the API? can you maybe allow or even default to preferring non-galaxy setup files?
Baseball Stars 2 [2020914910]
Garou - Mark of the Wolves [1830215906]
Last Blade [2146639333]
Metal Slug [1136471182]
Metal Slug 2 [1241813850]
Metal Slug 3 [1370911530]
Metal Slug X [2046360890]
Shock Troopers [1633815479]
Shock Troopers: Second Squad [1816849333]
Twinkle Star Sprites [1955376433]
these games all have linux installers, but they give the message
This game does not support linux! Would you like to download the windows version to run under wine? [Y/n]
On the webpage these games list OSX and Linux installers as unsupported extras
Thanks to @MajorDangerNine for discovering this
Hello Nicohman,
First of all, I really like the program you are making! Keep up the good work!
Unfortunately I cannot get it to work properly. I logged in with a OAuth token, when i do wyvern ls, it shows the games I have but when I download I get this error:
Error downloading file. Error message:https://gog.com/downloads/dead_cells/en3installer0: error trying to connect: error:1414D172:SSL routines:tls12_check_peer_sigalg:wrong signature type:../ssl/t1_lib.c:1110:
Also when I try to login with my username and password I get this error:
ERROR 2019-08-17T07:06:41Z: wyvern: Could not login to GOG. ERROR 2019-08-17T07:06:41Z: wyvern: Error: Error(SessionNetwork(ReqwestError(Error(Hyper(Error(Connect, Custom { kind: Other, error: Ssl(Error { code: ErrorCode(1), cause: Some(Ssl(ErrorStack([Error { code: 336908658, library: "SSL routines", function: "tls12_check_peer_sigalg", reason: "wrong signature type", file: "../ssl/t1_lib.c", line: 1110 }]))) }, X509VerifyResult { code: 0, error: "ok" }) })), "https://gog.com/"))), State { next_error: None, backtrace: InternalBacktrace { backtrace: None } })
Hopefully it can be solved, I would love to use wyvern!
SSL: no alternative certificate subject name matches target host name 'demenses.net'
Hey when I try to install from binary it on a raspberry pi it starts compiling dependencies.
I imagine you don't host binaries for arm architectures?
I would like to get this working on raspberry pi so I can possibly look into a converter for for example retropie, so I can download dosbox based games from gog, and convert the settings files, or image files to be run from dosbox on linux, and be put into launcher entries in EmulationStation.
I'm guessing it's not taking pagination into account?
There's exactly 100 games per page in the store's game list.
OS info:
██████████████████ ████████ bant@floyd
██████████████████ ████████ OS: Manjaro 18.0.2 Illyria
██████████████████ ████████ Kernel: x86_64 Linux 4.14.94-1-MANJARO
██████████████████ ████████ Uptime: 37m
████████ ████████ Packages: 1280
████████ ████████ ████████ Shell: zsh 5.6.2
████████ ████████ ████████ Resolution: 1920x1200
████████ ████████ ████████ WM: i3
████████ ████████ ████████ GTK Theme: Adapta-Nokto-Eta-Maia [GTK2/3]
████████ ████████ ████████ Icon Theme: Papirus-Adapta-Nokto-Maia
████████ ████████ ████████ Font: Noto Sans 10
████████ ████████ ████████ CPU: Intel Core i7-7500U @ 4x 3.5GHz [54.0°C]
████████ ████████ ████████ GPU: Mesa DRI Intel(R) HD Graphics 620 (Kaby Lake GT2)
████████ ████████ ████████ RAM: 5965MiB / 24007MiB
This happens on wyvern installed via cargo
on Rasbian Buster when trying to download my full games library. (for now I've just wrapped it in a while loop that continues until exit code is 0, it does get to download few gigabytes every time before crashing, so I can still make progress)
name = 'wyvern'
operating_system = 'unix:Unknown'
crate_version = '1.4.1'
explanation = '''
Panic occurred in file 'src/libcore/result.rs' at line 1188
'''
cause = 'called `Result::unwrap()` on an `Err` value: Error(Io(Custom { kind: TimedOut, error: "timed out" }), State { next_error: None, backtrace: InternalBacktrace { backtrace: None } })'
method = 'Panic'
backtrace = '''
0: 0x98611c - core::result::unwrap_failed::h6f265d930aca7ba0
at /usr/src/rustc-1.41.1/src/libcore/result.rs:1188
1: 0x52d2fc - wyvern::games::download::download_prep::h25ea0ce7c56e8db1
2: 0x4dd7bc - wyvern::parse_args::hbf1cb48c0dbb5a60
3: 0x4db364 - wyvern::main::hba3c02c2804132ac
4: 0x534928 - std::rt::lang_start::{{closure}}::h323683cfed830603
5: 0x96da2c - std::rt::lang_start_internal::{{closure}}::hd577abfa6cbb5c86
at /usr/src/rustc-1.41.1/src/libstd/rt.rs:52
- std::panicking::try::do_call::hc3f947477ee8c99a
at /usr/src/rustc-1.41.1/src/libstd/panicking.rs:292
6: 0x97074c - __rust_maybe_catch_panic
at /usr/src/rustc-1.41.1/src/libpanic_unwind/lib.rs:78
7: 0x95b9c8 - std::panicking::try::h418b59a1b5e34b4e
at /usr/src/rustc-1.41.1/src/libstd/panicking.rs:270
- std::panic::catch_unwind::he1fef2aa549f171b
at /usr/src/rustc-1.41.1/src/libstd/panic.rs:394
- std::rt::lang_start_internal::he16591861f8071f7
at /usr/src/rustc-1.41.1/src/libstd/rt.rs:51
8: 0x4e3248 - main
9: 0xb6a33718 - __libc_start_main'''
If you do Ctrl+C during download, making an unfinished download. Please clean up before exiting.
Or if you want to implement resuming downloads, maybe append .tmp
to the file during downloads.
It would be super nice to get a few extra features in the extras subcommand.
wyvern extras --all --id 1207666073 --output folder-name
I'd like to decide both the specific game, not searching for a name, and selecting what folder to download to. This would practically fix #17 for me.
Sometimes I get errors like
ERROR 2019-06-18T21:09:40Z: gog::token: Login failed. Incorrect credentials
ERROR 2019-06-18T21:09:40Z: wyvern: Could not login to GOG.
ERROR 2019-06-18T21:09:40Z: wyvern: Wrong email or password. Sometimes this fails because GOG's login form can be inconsistent, so you may just need to try again.
Which are totally fair. I just wonder if you could add a retuncodes so I can react to them more easily.
Could you have the option to return in json instead of plain text?
Right now I do crazy stuff like
mapfile -t myLibrary < <(wyvern ls | perl -pe 's:\ -\ (?!.*\ -\ ):;:g' | awk -F';' '{print $2 "\n" $1}')
😄
So either I'm too stupid to use this, it's not properly documented or I am encountering a bug:
$ wyvern ls
It appears that you have not logged into GOG. Please pick a login method.
Login Method:
OAuth Token Login
Username/Password Login
so far so good. But as soon as I press any button, the text below Login Method:
disappears and nothing happens anymore, also no characters that I type are displayed. Should I type something into a password field or should there appear something that doesn't?
I don't want to put my password into my bash-history, so I would prefer an interactive login method.
Distro: Archlinux
Version: wyvern 1.4.0
- installed from AUR an hour or so ago.
Can i select files to download (not extras or dlc but the main game installer)? If i have an installer weighing 47 GB i might not want to start downloading all 21 files but only the last if something went wrong...
I've ran into an issue when updating certain games, different from #15. So far i've encountered this when updating BattleTech, Tower of Time and SOMA.
mike@bigrig:~/GOG Games/BATTLETECH$ RUST_BACKTRACE=1 wyvern -vvvv update
INFO 2019-03-19T19:17:27Z: wyvern: Path not specified. Using current dir
INFO 2019-03-19T19:17:27Z: wyvern: Updating game
INFO 2019-03-19T19:17:27Z: wyvern::games::update: Reading in gameinfo file
INFO 2019-03-19T19:17:27Z: wyvern::games::update: Parsing gameinfo
INFO 2019-03-19T19:17:27Z: wyvern::config: Getting name from gameinfo
INFO 2019-03-19T19:17:27Z: wyvern::config: Getting version string from gameinfo
INFO 2019-03-19T19:17:27Z: wyvern::games::update: Searching GOG products for BATTLETECH
INFO 2019-03-19T19:17:28Z: wyvern::games::update: Fetching the GameDetails for first result of search
INFO 2019-03-19T19:17:29Z: wyvern::games::update: Getting game's linux downloads
INFO 2019-03-19T19:17:29Z: wyvern::games::update: Fetching installer data.
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: UnexpectedEof, error: StringError("failed to fill whole buffer") }', src/libcore/result.rs:997:5
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:70
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:58
at src/libstd/panicking.rs:200
3: std::panicking::default_hook
at src/libstd/panicking.rs:215
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:478
5: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:385
6: rust_begin_unwind
at src/libstd/panicking.rs:312
7: core::panicking::panic_fmt
at src/libcore/panicking.rs:85
8: core::result::unwrap_failed
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libcore/macros.rs:16
9: <core::result::Result<T, E>>::unwrap
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libcore/result.rs:798
10: gog::extract::CDEntry::from_reader
at /home/mike/.cargo/git/checkouts/gog-rs-3c06ac510bb5cd16/0d2a926/src/extract.rs:175
11: gog::Gog::extract_data
at /home/mike/.cargo/git/checkouts/gog-rs-3c06ac510bb5cd16/0d2a926/src/lib.rs:752
12: wyvern::games::update::update
at src/games.rs:38
13: wyvern::parse_args
at src/main.rs:397
14: wyvern::main
at src/main.rs:89
15: std::rt::lang_start::{{closure}}
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/rt.rs:64
16: std::panicking::try::do_call
at src/libstd/rt.rs:49
at src/libstd/panicking.rs:297
17: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:92
18: std::rt::lang_start_internal
at src/libstd/panicking.rs:276
at src/libstd/panic.rs:388
at src/libstd/rt.rs:48
19: std::rt::lang_start
at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/rt.rs:64
20: main
21: __libc_start_main
22: _start
Could you implement wyvern login --status
and wyvern login --status --json
to give information like if you are logged in, what is your user-name, and maybe more?
some characters are not preserved, like (
and )
which are written out as %28
and %29
respectively.
Would it be okay to get a commandline flag to get another kind of progress bar?
Just echo a new line with the percent whenever a new whole number percent is reached?
1
2
3
4
5
6
7
I know wget has a --progress=type
flag, and I have seen people pipe wget with progress=dot through awk and sed to get just the percent.
I don't know, maybe the argument could be called --progress=dumb
If you add other aesthetic types, maybe the user preferred one could be put in the config file. I know pacman has an option to let the progress bar be a pacman that eats dots, thats always funny if you run arch linux.
Can you implement fetching some metadata before downloading?
Wishlist:
Hi,
I'm running ''s saves are located
'wyvern -vvvv int'
It appears that you have not logged into GOG. Please pick a login method.
Login Method:
I can try to put '0' or '1', but nothing changes on the screen then. Een ton't know how to select if I want to use OAuth or User/Pass login method.
Wyvern straight frm AUR, 1.4.1-3
I suggest switching to Letsencrypt
sudo curl -o wyvern -O https://demenses.net/wyvern-nightly
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
curl: (60) SSL certificate problem: certificate has expired
More details here: https://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
User @CountMetal opened an issue over at my place. sigboe/pie-galaxy#11 where your site seams to be offline.
Will we be expecting this to come back up?
So far wyvern down
and wyvern extras
both support the --output flag. But wyvern down -a
does not create folders per game. wyvern extras
does, so one might end up with a folder full of install files, patch files and a bunch of subdirs for extras. And still wyvern extras
needs to be called per game.
I have > 50 games on gog so this is not tidy enough for me. It would be very nice for wyvern to have an option to automatically create one folder per game based on the metadata received from gog.com (e.g. game title).
Until then this script might come in handy (it mentions zsh, but should run on bash, too) (it requires: wyvern, json_pp and jq):
#!/bin/bash
GAMESDIR=SOMEPLACE/gog-games
(
cd $GAMESDIR
wyvern ls --json | json_pp > ALLGAMES
for row in `jq -r '.games[].ProductInfo | {title: .title, id: .id} | @base64' ALLGAMES`
do
R=`echo ${row} | base64 --decode`
D=`echo $R | jq -r '.title'`
I=`echo $R | jq -r '.id'`
echo Downloading $D
mkdir "$D"
cd "$D"
wyvern down -D -r -w --id $I
wyvern extras -a --id $I
cd -
done
) 2>&1 | tee -a $GAMESDIR/log-`date +%Y-%m-%d`.log
Update: redirection of stderr fixed, uses bash
Would it be feasible to have an interactive login method?
Also supporting entering the pin if you log in from a new IP address.
I looked slightly into using curl to do this, but I didn't look into it thoroughly.
I tried something like this https://github.com/sigboe/glaxy-pie/blob/a54c57eb437fe9e02c409c2a3b6097d2df2133fd/galaxy-pie.sh#L85-L95
If you cold download single extras if you knew the slug, then check out the v2 api.
curl -s https://api.gog.com/v2/games/1207658787?locale=en | jq '._embedded | .bonuses[] | .type'
I there are more things in the way to download a single extra, then feel free to close this issue.
Logging in with user/pass and downloading one 4GB+ game part, (witcher 3) my session times out with GOG.com and subsequent file retreivals in the set all faill, creating files named e1installer [18-23] the files contain the text:
{"error":"invalid_grant","error_description":"The access token provided has expired."}
Subsequent redownload of the game results in wyvern creating another copy of the first file.
Hoped-for behavior:
Cheers!
Last two days or maybe three days, I have been unable to compile
sigurdb@zig-pc-04 ~/Documents/wyvern (git)-[master] % cargo install --path . --force
Installing wyvern v1.2.1 (/home/sigurdb/Documents/wyvern)
Updating crates.io index
error: failed to compile `wyvern v1.2.1 (/home/sigurdb/Documents/wyvern)`, intermediate artifacts can be found at `/home/sigurdb/Documents/wyvern/target`
Caused by:
failed to load source for a dependency on `dialoguer`
Caused by:
Unable to update /home/sigurdb/Documents/wyvern/src/dialoguer
Caused by:
failed to read `/home/sigurdb/Documents/wyvern/src/dialoguer/Cargo.toml`
Caused by:
No such file or directory (os error 2)
Could you please add a way to login like so?
wyvern login --email "${email}" --password "${password}"
Oh and the most common convention is if you don't have the --password
parameter, you would be able to type that after, to not pollute your bash history.
Maybe
wyvern login --token "${token}"
should also work
I am looking into the possibility of making a curses (or something) frontend for retropie that will download and convert dosbox games to hopefully work in retropie.
I am currently downloading a game like this
wyvern down --id 1207659026 --windows-auto
The resulting filename should maybe have the .exe file ending?
I have successfully extracted an installer using innoextract which is in the raspbian (and debian) repositories like this.
innoextract --exclude-temp -gog filename
Is extracting the exe files something you think you would integrate into Wyvern?
Login via login -u xxx -p xxx
does not work. Even if I get to enter the 2FA, it just creates a empty wyvern.toml including only version = 1
Also happens if I delete the wyvern.toml and get past the 2FA on the first try, so it does not seam to have an issue overwriting the file.
arm binary is not in the last major release. Is it manually compiled or was the buildbot supposed to build it?
Being able to decide where to download, and decide an output filename would be great.
Example:
wyvern down --id 1234 -o ~/Downloads/ #I just want to pick a folder
wyvern down --id 1234 -o ~/Downloads/myfilename.exe #I want to pick a fully qualified name
Being able to perserve the fileextension if you didnt pick one or using a flag would be even greater
wyvern down --id 1207659026 -o ~/Downloads/Theme\ Hospital/1207659026 --preserve-fileextension
#I want t pick a folder and a name, but I don't want to care about the extension.
I just wanted to report some crashes I'm getting when I tried wyvern.
I get the following anytime I run the "ls" command, and when attempting to update certain games, such as Tower of Time. The backtrace is identical in both cases.
name = 'wyvern'
operating_system = 'unix:Ubuntu'
crate_version = '1.3.1'
explanation = '''
Panic occurred in file 'src/libcore/result.rs' at line 997
'''
method = 'Panic'
backtrace = '''
stack backtrace:
0: backtrace::backtrace::trace_unsynchronized::h1329a2593493e9a4 (0x5596ba11b856)
1: backtrace::capture::Backtrace::create::h16101f07b59a61ea (0x5596ba11ac77)
2: backtrace::capture::Backtrace::new::h71f40c1b075807a9 (0x5596ba11ab9d)
3: human_panic::report::Report::new::h7ca9937bcaa66099 (0x5596ba074742)
4: human_panic::handle_dump::h7be66dc999882f6f (0x5596ba073e17)
5: wyvern::main::{{closure}}::h24d4f5a3c90a0f57 (0x5596b9d71798)
6: std::panicking::rust_panic_with_hook::h744417edfe714d72 (0x5596ba19c3e9)
at src/libstd/panicking.rs:482
7: std::panicking::continue_panic_fmt::h3557b3c3fa21b47b (0x5596ba19be91)
at src/libstd/panicking.rs:385
8: rust_begin_unwind (0x5596ba19bd75)
at src/libstd/panicking.rs:312
9: core::panicking::panic_fmt::h74ee8034b317ceed (0x5596ba1b99fc)
at src/libcore/panicking.rs:85
10: core::result::unwrap_failed::hd485e30a906e635d (0x5596b9da0dc9)
11: wyvern::parse_args::hc891995a89059041 (0x5596b9d6edd1)
12: wyvern::main::hb228d5a73bc9c62c (0x5596b9d6ac1e)
13: std::rt::lang_start::{{closure}}::h8560fca4078eb982 (0x5596b9d7321f)
14: std::rt::lang_start_internal::{{closure}}::h8ad4264c6b68797c (0x5596ba19bd12)
at src/libstd/rt.rs:49
std::panicking::try::do_call::h7a0381557c6c2cee
at src/libstd/panicking.rs:297
15: __rust_maybe_catch_panic (0x5596ba1a5729)
at src/libpanic_unwind/lib.rs:92
16: std::panicking::try::h72cb0fef6e9c0ab1 (0x5596ba19c925)
at src/libstd/panicking.rs:276
std::panic::catch_unwind::hbff071ae76e6f224
at src/libstd/panic.rs:388
std::rt::lang_start_internal::he0d8d06abc6f912f
at src/libstd/rt.rs:48
17: main (0x5596b9d71811)
18: __libc_start_main (0x7fc164107b96)
19: _start (0x5596b9d22839)
20: <unknown> (0x0)'''
Great Idea, especially the delta-downloads.
There is one thing, i would like to see, and that is downloading of DLCs for the games. Downloading the Extras (Soundtrack, etc) if available would be a nice to have, if download of DLCs is easy to implement.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.