Giter Club home page Giter Club logo

dns.toys's Introduction

dns.toys is a DNS server that takes creative liberties with the DNS protocol to offer handy utilities and services that are easily accessible via the command line.

For docs, visit www.dns.toys

Sample commands

dig help @dns.toys

dig mumbai.time @dns.toys

dig 2023-05-28T14:00-bengaluru-berlin/de.time @dns.toys

dig newyork.weather @dns.toys

dig 42km-mi.unit @dns.toys

dig 100USD-INR.fx @dns.toys

dig ip @dns.toys

dig 987654321.words @dns.toys

dig pi @dns.toys

dig 100dec-hex.base @dns.toys

dig fun.dict @dns.toys

dig A12.9352,77.6245/12.9698,77.7500.aerial @dns.toys

Running locally

  • Clone the repo
  • Copy config.sample.toml to config.toml and edit the config
  • Make sure you have a copy of the cities15000.txt file at the root of this directory (instructions are in the config.sample.toml file)
  • Make sure to download the wordnet from Wordnet website.(more instructions are in the config.sample.toml file)
  • Extract the tarball and rename extracted the directory to wordnet
  • Run make build to build the binary and then run ./dnstoys.bin
  • Query against the locally running server
    dig <query> +short @127.0.0.1 -p 5354

Others

dns.toys's People

Contributors

aneeraj avatar chessmango avatar dependabot[bot] avatar efallancy avatar geekbala avatar hold7door avatar jadonclegg avatar knadh avatar legosandorigami avatar libdarkstreet avatar michals avatar mikolysz avatar mr-karan avatar mrmadfox avatar neomantra avatar srijanshetty avatar stemid avatar subhadipghs avatar teutat3s avatar varunlakkur avatar vicne avatar xen0l avatar yashvardhan-kukreja avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dns.toys's Issues

Small cities not working for weather

I checked on yr.no and they have the location available, but I can't search it with dig; it appears several several friends of mine live in (cumming and buford) cannot be looked up oddly, while places like 'broken arrow', modesto, and other small cities are easily searchable even as simple as west palm beach

$ sdig 'lawrenceville/US.weather' @dns.toys
lawrenceville. 1 IN TXT "Lawrenceville (US)" "31.20C (88.16F)" "58.40% hu." "lightrainshowers_day" "17:00, Mon"
lawrenceville. 1 IN TXT "Lawrenceville (US)" "30.10C (86.18F)" "62.50% hu." "partlycloudy_day" "19:00, Mon"
lawrenceville. 1 IN TXT "Lawrenceville (US)" "27.20C (80.96F)" "78.90% hu." "partlycloudy_night" "21:00, Mon"
lawrenceville. 1 IN TXT "Lawrenceville (US)" "25.90C (78.62F)" "86.80% hu." "fair_night" "23:00, Mon"
lawrenceville. 1 IN TXT "Lawrenceville (US)" "24.70C (76.46F)" "90.70% hu." "partlycloudy_night" "01:00, Tue"

$ dig 'cumming/US.weather' @dns.toys

;; QUESTION SECTION:
;cumming/US.weather. IN A

;; ADDITIONAL SECTION:
. 1 IN TXT "error: unknown city."

$ dig 'Buford/US.weather' @dns.toys

; <<>> DiG 9.11.5-P4-5-Debian <<>> Buford/US.weather @dns.toys
;; QUESTION SECTION:
;Buford/US.weather. IN A

;; ADDITIONAL SECTION:
. 1 IN TXT "error: unknown city."

;; Query time: 76 msec

Add a dice-rolling feature

I propose adding a dice-rolling and random number generation feature, useful when E.G. playing tabletop RPG games, or when not sure which option/person to pick for something.

The feature should consist of two services, .dice and .random. The first service should accept requests in the standard format kdn(+m.)dice, where k, n and m are numbers. For example:

  • 1d6.dice is a standard roll with a single die.
  • 2d6 is a roll of two standard dice, as used in Monopoly and other board games.
  • 3d20+5.dice is a roll of three 20-sided dice, with 5 added to the total. Such rolls are used in Dungeons and Dragons and other similar games.

I'm not sure if DNS considers + as an acceptable character, if not, we can use / instead.

The service should return the results for each roll separately, as well as the total of all rolls + the modifier.

The second service should accept requests in the format n-m.random, and return a random number between n and m (inclusive).

I'm willing to work on this personally if @knadh considers this useful enough to merge, but I'd love to get their opinion on this first so that my work doesn't go to waste.

Units and case-sensitivity

Some units are case-sensitive, for instance MB and Mb are different things. But the DNS is case-insensitive, which means that this behavior is logical, but surprising:

% dig 32GB-Mb.unit @dns.toys

; <<>> DiG 9.18.1-1ubuntu1.2-Ubuntu <<>> 32GB-Mb.unit @dns.toys
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10293
;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;32GB-Mb.unit.		IN A

;; ANSWER SECTION:
32GB-Mb.		1 IN TXT "32.00 Gigabyte (GB) = 256000.00 Megabit (Mb)"

;; Query time: 84 msec
;; SERVER: 2604:a880:400:d0::1352:6001#53(dns.toys) (UDP)
;; WHEN: Mon Sep 26 14:01:38 CEST 2022
;; MSG SIZE  rcvd: 94

% dig 32GB-MB.unit @dns.toys

; <<>> DiG 9.18.1-1ubuntu1.2-Ubuntu <<>> 32GB-MB.unit @dns.toys
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37544
;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;32GB-MB.unit.		IN A

;; ANSWER SECTION:
32GB-MB.		1 IN TXT "32.00 Gigabyte (GB) = 32000.00 Megabyte (MB)"

;; Query time: 84 msec
;; SERVER: 2604:a880:400:d0::1352:6001#53(dns.toys) (UDP)
;; WHEN: Mon Sep 26 14:01:39 CEST 2022
;; MSG SIZE  rcvd: 94

This is even worse if DNS requests go through a forwarder which downcases everything (a bad idea, but it may happen). May be a word in the documentation?

Explicit IPv4 support

Currently, in the case of dual-stack (where v4 and v6 are assigned) dig ip @dns.toys always returns a v6 address. It would be great to have the IP query return the v4 address when mentioned.

I am willing to work on this.

About .NET Library and NuGet Package

First of all, thanks for this service. It's great.

I've developed a client library for interacting with dns.toys. It was also fun. It's in my profile, you can reach it from here.
I've also published a package called DnsToys to NuGet, it's here.

Would you consider adding a section for the package?

howdoi

Hi, this is awesome!

In particular, it should be useful for wifi hotspots where DNS works without login.

It would be cool to combine this with howdoi: https://pypi.org/project/howdoi/

By this I mean: query dig howdoi.format.date.bash @dns.toys, receive as response from the server (which replaced '.' with ' ', passed to howdoi) date +%Y-%m-%d

Actually useful: IANA timezone database over DNS

Look up the current UTC offset, the next switching date/time and the UTC offset after the switch for a named time zone.

DNS is actually a very efficient way to distribute this small but important pieces of information. If this is done on a zone attached to a real TLD it could instruct recursive DNS servers to set a very long expiration time. It can also pass through many firewalls.

Small misspelling at help response

When running the command dig help @dns.toys you get the following response:

...
help.                   1       IN      TXT     "return pi as TXT or A or AAAA record." "dig ip @dns.toys"
...

It should probably say "return ip as TXT ..."

Add AES encryption key generator

We use AES encryption in our codebase to encrypt stuff, And I see people regularly putting wrong keys. So add the AES key generator in dns.toys to make it easier for people to generate AES enc key.

Support for listing CIDR range

I often use https://cidr.xyz/ to see the usable IP range for a given CIDR notation.

Something like this in dns.toys would be super useful:

dig 10.0.0.1/24.cidr @dns.toys

10.0.0.1/24.			1	IN	TXT	 "10.0.0.1 - 10.0.0.254" "256"

I can work on a PR, if you're open to add support for this.

Support for epoch conversions

I had worked on adding support for epoch time conversions to human readable on my fork.

% dig 784783800.epoch @127.0.0.1 -p 5354   

;; QUESTION SECTION:
;784783800.epoch.		IN	A

;; ANSWER SECTION:
784783800.		1	IN	TXT	"1994-11-14 09:00:00 +0530 IST"

If you are okay with this, I can send in the PR.

Thanks and have a happy weekend! ๐Ÿ™‚

Wrong data on the first query for weather

Today (Sun Jan 07 2024) I performed two queries about weather. The first one showed data for Wed/Thu. The second one, made several seconds later, showed proper data. I checked several other cities - all seem to have the same issue. Looks like some kind of cache issue for me.

First one:

dig poznan.weather @dns.toys

; <<>> DiG 9.19.19-1-Debian <<>> poznan.weather @dns.toys
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52372
;; flags: qr rd; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;poznan.weather.			IN	A

;; ANSWER SECTION:
poznan.			1	IN	TXT	"Poznan (PL)" "0.40C (32.72F)" "98.10% hu." "cloudy" "22:00, Wed"
poznan.			1	IN	TXT	"Poznan (PL)" "0.50C (32.90F)" "96.30% hu." "cloudy" "00:00, Thu"
poznan.			1	IN	TXT	"Poznan (PL)" "0.40C (32.72F)" "95.50% hu." "cloudy" "02:00, Thu"
poznan.			1	IN	TXT	"Poznan (PL)" "0.20C (32.36F)" "95.20% hu." "lightsnow" "04:00, Thu"
poznan.			1	IN	TXT	"Poznan (PL)" "0.00C (32.00F)" "94.80% hu." "snow" "06:00, Thu"

;; Query time: 136 msec
;; SERVER: 204.48.19.68#53(dns.toys) (UDP)
;; WHEN: Sun Jan 07 09:04:55 CET 2024
;; MSG SIZE  rcvd: 403

Second one:

dig poznan.weather @dns.toys

; <<>> DiG 9.19.19-1-Debian <<>> poznan.weather @dns.toys
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9946
;; flags: qr rd; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;poznan.weather.			IN	A

;; ANSWER SECTION:
poznan.			1	IN	TXT	"Poznan (PL)" "-6.20C (20.84F)" "63.40% hu." "cloudy" "10:00, Sun"
poznan.			1	IN	TXT	"Poznan (PL)" "-6.20C (20.84F)" "59.70% hu." "cloudy" "12:00, Sun"
poznan.			1	IN	TXT	"Poznan (PL)" "-6.70C (19.94F)" "59.10% hu." "cloudy" "14:00, Sun"
poznan.			1	IN	TXT	"Poznan (PL)" "-7.60C (18.32F)" "61.80% hu." "cloudy" "16:00, Sun"
poznan.			1	IN	TXT	"Poznan (PL)" "-8.00C (17.60F)" "62.20% hu." "cloudy" "18:00, Sun"

;; Query time: 104 msec
;; SERVER: 204.48.19.68#53(dns.toys) (UDP)
;; WHEN: Sun Jan 07 09:05:18 CET 2024
;; MSG SIZE  rcvd: 407

Outdated FX

If I run the example included in dig help @dns.toys, I get the following:

โžœ dig 99USD-INR.fx @dns.toys

; <<>> DiG 9.16.44 <<>> 99USD-INR.fx @dns.toys
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19665
;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;99USD-INR.fx.                  IN      A

;; ANSWER SECTION:
99USD-INR.              3600    IN      TXT     "99.00 USD = 8172.15 INR" "2023-05-28"

;; Query time: 64 msec
;; SERVER: 204.48.19.68#53(204.48.19.68)
;; WHEN: Mon Jan 15 05:19:24 PST 2024
;; MSG SIZE  rcvd: 86

There is an old (closed) issue that suggests adjusting the config.toml to avoid this, but this behavior seems unrelated -- the data is from over half a year ago, which is well above the default refresh rate of 6 hours.

Support for IPv6

Please add support for IPv6 to retrieve IPv6 addresses using "dig ip @dns.toys" or "dig ipv6 @dns.toys".

Unfortunately, the domain dns.toys is not IPv6 activated yet.

;; QUESTION SECTION:
;dns.toys. IN AAAA

;; AUTHORITY SECTION:
dns.toys. 1800 IN SOA matt.ns.cloudflare.com. dns.cloudflare.com. 2279935843 10000 2400 604800 3600

Help Pi Typo

I noticed a small typo in the help output:

$ dig help @dns.toys | grep pi
help.                   1       IN      TXT     "return pi as TXT or A or AAAA record." "dig ip @dns.toys"

In the example command ip should be changed to pi

Support for finding definitions and meanings of words

Thanks for this. Recently started learning GO. Thought this might be a good exercise.

I worked on adding support for a dictionary service. So you can find definition of a word in different parts of speech like this -

dig play.dictionary @dns.toys

play.                   1       IN      TXT     "noun:" "Activity for amusement only, especially among the young."
play.                   1       IN      TXT     "verb:" "To act in a manner such that one has fun; to engage in activities expressly for the purpose of recreation or entertainment."

Internally, it uses the API from https://dictionaryapi.dev/. Response from the API can be large with multiple meanings, and DNS packet size has limits, so the result from service is trimmed a bit to fetch one definition per part of speech.

A lot of reference for implementation was taken from the weather service.

It's on my forked repo at - https://github.com/hold7door/dns.toys/tree/dictionary.

If you are okay with it, I'll submit a PR.

Support for network speed

Hi,

It would be helpful if we could also monitor upload/download speed using this.
Something like:

dig download.speed @dns.toys
dig upload.speed @dns.toys

Is it ok if I work on a PR for the same?

Long responses may be a security issue

Since some responses (for instance weather or dictionary) are way larger than the queries, and since dns.toys accepts requests over UDP, it may be used for reflection attacks with amplification. I don't think it is currently a deadly risk for the Internet :-) but may be some rate-limiter would be a good idea.

Incorrect day of week when querying weather

$ dig amsterdam.weather @dns.toys

; <<>> DiG 9.16.8-Ubuntu <<>> amsterdam.weather @dns.toys
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14217
;; flags: qr rd; QUERY: 1, ANSWER: 10, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;amsterdam.weather.		IN	A

;; ANSWER SECTION:
amsterdam.		1	IN	TXT	"Amsterdam (NL)" "15.70C (60.26F)" "86.30% hu." "lightrain" "09:00, Wed"
amsterdam.		1	IN	TXT	"Amsterdam (NL)" "16.00C (60.80F)" "83.40% hu." "rain" "11:00, Wed"
amsterdam.		1	IN	TXT	"Amsterdam (NL)" "15.70C (60.26F)" "87.20% hu." "heavyrain" "13:00, Wed"
amsterdam.		1	IN	TXT	"Amsterdam (NL)" "15.30C (59.54F)" "91.00% hu." "rain" "15:00, Wed"
amsterdam.		1	IN	TXT	"Amsterdam (NL)" "15.80C (60.44F)" "90.20% hu." "rain" "17:00, Wed"
amsterdam.		1	IN	TXT	"Amsterdam (US)" "17.20C (62.96F)" "95.60% hu." "cloudy" "03:00, Wed"
amsterdam.		1	IN	TXT	"Amsterdam (US)" "15.70C (60.26F)" "97.40% hu." "cloudy" "05:00, Wed"
amsterdam.		1	IN	TXT	"Amsterdam (US)" "14.80C (58.64F)" "95.80% hu." "fair_day" "07:00, Wed"
amsterdam.		1	IN	TXT	"Amsterdam (US)" "16.60C (61.88F)" "80.60% hu." "cloudy" "09:00, Wed"
amsterdam.		1	IN	TXT	"Amsterdam (US)" "19.60C (67.28F)" "61.00% hu." "partlycloudy_day" "11:00, Wed"

;; Query time: 92 msec
;; SERVER: 138.197.68.199#53(138.197.68.199)
;; WHEN: Wed Jun 08 09:45:40 CEST 2022
;; MSG SIZE  rcvd: 857

I'm not sure, but my guess is that this is weather for today and tomorrow. Probably the last 5 entries here should say "Thu" instead of "Wed".

Add support for English to Other Language translation support

I propose adding support for translation from English to any other language. This can be useful while trying to convey something in other languages or just for fun. This is intended not be used to translate entire text or document but only for small use cases like wanting to translate say a number 50 in English to Hindi and for such scenarios.

The feature would use .translate to initiate it. It should accept the text in English to translate and the target language to which it should be translated. The format could be something like

dig hello-hindi.translate @dns.toys

or if we intend to support multiple words with a size limit then it could be like

dig hello_world.translate @dns.toys

where multiple words are separated by an "underscore". Hopefully underscore is a valid character in DNS.

The feature should consist of two services, .dice and .random. The first service should accept requests in the standard format kdn(+m.)dice, where k, n and m are numbers. For example:

Do let me know if this makes any sense. @knadh
I can work on this if this is approved and this is my first try at contributing to open source. If there's something else I can pick up would be glad to try it out as well. Thanks in advance.

Support for coin toss

$ dig coin @dns.toys
;; ANSWER SECTION:
coin.                   1       IN      TXT     "tossed = [heads]"
$ dig 2.coin @dns.toys
;; ANSWER SECTION:
coin.                   1       IN      TXT     "tossed = [heads, tails]"
$ dig 42.coin @dns.toys

;; ADDITIONAL SECTION:
.                       1       IN      TXT     "error: toss overflow"

Error to convert cidr to ip range

I got this error:
`dig 10.100.0.0/24 @dns.toys
;; Warning: query response not set

; <<>> DiG 9.16.1-Ubuntu <<>> 10.100.0.0/24 @dns.toys
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 25240
;; flags: rd ad; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;10.100.0.0/24. IN A

;; ADDITIONAL SECTION:
. 1 IN TXT "error: unknown query. try: dig help @dns.toys"

;; Query time: 116 msec
;; SERVER: 138.197.68.199#53(138.197.68.199)
;; WHEN: Thu Jun 09 11:01:16 EEST 2022
;; MSG SIZE rcvd: 88
`

Guide to Run it Locally

I went through the README.md file to run DNS Toys locally but I am not able to somehow do it ,

Can you guys provide some video in which you set-up DNS Toys Locally ,

That would be really helpful !

Thanks

Lookup ASN and AS Name

One thing that is pretty common in the network engineering field is to look up an IP's AS Number and/or looking up an ASN's name based on its number. I think it'd be a very useful addition to dns toys.

There's a lot of ways to implement this:

  • acting as a proxy for the CYMRU DNS service (with or without using an external dependency)
  • using HTTP API services
  • Implementing the lookup internally and pre-caching/refreshing the data periodically. I'm figuring that's probably a point best left for discussion.

Draft usage example:

# Lookup an ASN 
% dy 8.8.8.8.origin
% dy 2001:4860:4860::8844.origin
"15169"  # simplified form
"AS15169"  # alternative
"15169 | 8.8.8.0/24 | US | arin | 2023-12-28"  # Same output that CYMRU uses; has the most information in it
"AS15169 GOOGLE, US"  # Another acceptable output, cidr-report.org format


% dy 15619.asn
% dy as15619.asn
"GOOGLE, US"  # Simplest form
"AS15169 GOOGLE, US"  # cidr-report.org format
"15169 | US | arin | 2000-03-30 | GOOGLE, US"  # Same output that CYMRU uses; has the most information in it

References:

Support number conversion between bases

I often use calculator to convert from hex to decimal, decimal to binary and such. It would be useful to add support for this conversion in dns.toys. Something like this:

Example 1:

dig 11234dec-hex.base @dns.toys

1234HEX-DEC.		1	IN	TXT	"1234 HEX = 4660 DEC"

Example 2:

dig 1234dec-bin.base @dns.toys

1234DEC-BIN.		1	IN	TXT	"1234 DEC = 10011010010 BIN"

Add Aerial Distance Calculation

I frequently find myself finding distance between two points on a random website. Will love if this is handled by dns.toys

For the query dig 12.9352,77.6245,12.9698,77.7500.aerial @dns.toys

and the server responds with Aerial Distance is 14.13 KMs

The issue however I am having is that in the Query method, I am not able to get delimiter , properly,

eg. for the above command, the query string q received in the function is
12.935277.624512.969877.7500

I am trying to add this feature via draft PR #47

It's still a WIP as I have to figure out this and add tests.

Numbers support is limited

It seems that number to words support is limited only to bilions, after that the last digits with billion are used which results in wrong results:

e.g.

dig 9876543210000000.words @dns.toys

should be

nine quadrillion ,
eight hundred seventy six trillion ,
five hundred forty three billion ,
two hundred ten million 

however the output is

9876543210000000 = five hundred forty-three billion two hundred ten million"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.