Giter Site home page Giter Site logo

operationcode / operationcode-pybot Goto Github PK

View Code? Open in Web Editor NEW
32.0 8.0 45.0 9.19 MB

Operation Code's Official Slackbot

License: Other

Python 98.30% Dockerfile 0.63% Shell 1.03% Procfile 0.04%
python slackbot slack-api hacktoberfest hacktoberfest2020 hacktoberfest2019 hacktoberfest2018 hacktoberfest2017

operationcode-pybot's Introduction

License: MIT Twitter Follow Code-style: black

PRs Welcome

OperationCode-Pybot

OperationCode PyBot is a Python Slack Bot utilizing Slack Bolt.

Resources

Contributing

Bug reports and pull requests are welcome on our Github repo. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct. The best place to get assistance with OperationCode-Pybot is on Slack in the #oc-python-project channel.

Quick Start

Recommended versions of tools used within the repo:

  • [email protected] or greater
  • [email protected] or greater - pipenv is a package manager similar to poetry that utilizes pip to manage project dependencies, along with creating new virtual environments and deterministic builds
# Ensure you have pipenv already installed
pipenv install --dev

# Start up your virtual environment
pipenv shell

# Run the test suite
pytest

# Run the code formatter
black .

How to Test Integration with SlackAPI

In order to test the new methods and interactions you may have created already, you'll need an "app configuration token". In order to get one of those, you'll need to create a new issue. Please use the type: config token request label and make the title " Requests an App Config Token". For example: Judson Stevens Requests an App Config Token.

Once you have created your issue, one of the maintainers of this repository will get in touch and give you your token.

How to Test Integration With Slack

After having developed some new feature, or having in hand what you believe is a fix for an existing bug, how do you test it out in a real system in order to make sure that your changes do all that you hope they do? The answer; bring up the application in your own environment and hook it up to Slack!

In order to do this, you'll want to tackle the following items in order:

  1. Setup your own Slack workspace.
  2. Grab a signing secret from Slack that pybot can utilize.
  3. Launch pybot locally, passing it your Slack signing secret.
  4. Attach your pybot instance to the public internet so that Slack can speak with it.
  5. Point Slack at your running pybot instance, and properly configure it.

The following sections will guide you through each of these stages.

1 - Setup Your Own Slack Workspace

To start, you'll want to visit Slack's Getting Started page. From this page, follow the steps required to create a new workspace. The names/options you configure during creation don't matter so much, but make sure you associate it with an email address you have access to. Once complete it should present you with an option to login to the new workspace, make sure you go ahead and do that.

If you're having a hard time figuring this out, try checking out the following Slack article Create a Slack Workspace.

Create expected channels

Several of Pybot's features involve sending messages to specific channels - in order for this to work in your personal Slack workspace you'll need to create the following channels:

  • mentors-internal
  • greetings
  • moderators
  • oc-tech

2 - Create a pybot App in Your Slack Workspace

The next step is to create a new bot application in your workspace. While still logged in, visit the App Management page and choose to create a new app. During this process, make sure to copy down the signing secret key that gets generated for your app, as you'll need it later, following this, follow the guidelines for creating a bot app as laid out in the Enabling interactions with bots article. When you get to the stage of creating the bot user, make sure to write down the bot user OAuth access token that is presented, as you'll need to use it later.

On the OAuth & Permissions page configure the Pybot app with the following scopes

  • channels:manage
  • chat:write
  • chat:write.public
  • commands
  • users:read

3 - Launch pybot Locally, Passing in Your Signing Secret

With your Slack workspace, app and bot user created, and your app signing secret and bot user OAuth access token in hand, you should now be ready to configure pybot to integrate with your new Slack workspace. To do this, you'll first want to setup the proper configuration in pybot.

pybot configuration is specified completely through environment variables. When running locally, you can configure the ./docker/pybot.env file with the environment variable name/value pairings, which will get evaluated on application start. Otherwise, make sure to export or pass in the correct environment variables through your shell when launching pybot.

Here's an example of configuring these through the pybot.env file:

SLACK_BOT_SIGNING_SECRET=APP-SIGNING-SECRET
BOT_USER_OAUTH_ACCESS_TOKEN=BOT-USER-OAUTH-TOKEN

NOTE: More configuration settings than these may be specified. Please see the Known Configuration Settings section near the bottom of this document for details on other settings that can be set.

4 - Attach Your pybot Instance to the Public Internet

With an instance of pybot running, you now need to expose this instance to the public internet so Slack can send in API requests. You can easily utilize ngrok for this purpose if you wish. To do so; download ngrok from https://ngrok.com/download and set up a tunnel like so:

ngrok http 5000

Pay attention to copy out the response you get and keep this command running. Here's an example output from the command:

ngrok by @inconshreveable                                                                        (Ctrl+C to quit)
Session Status                online                                                                             
Session Expires               7 hours, 56 minutes                                                                
Version                       2.3.35                                                                             
Region                        United States (us)                                                                 
Web Interface                 http://127.0.0.1:4040                                                              
Forwarding                    http://9d73595a7aac.ngrok.io -> http://localhost:5000                              
Forwarding                    https://9d73595a7aac.ngrok.io -> http://localhost:5000                             
Connections                   ttl     opn     rt1     rt5     p50     p90                                        
                              0       1       0.00    0.00    0.00    0.00                                       
HTTP Requests 

With this done, ngrok will now expose the instance of pybot running locally on port 5000 via the "Forwarding" address it returns. Be sure to use the URL beginning with https.

5 - Point Slack at Your Running pybot Instance

With the initial Slack configuration complete and your instance of pybot running on the public internet, it is now the perfect time to fully configure Slack to interact with your bot. Depending on the interactions you're wanting to play with, there are various configurations you can specify, which can be broken down into the following parts:

  • Event Subscriptions - this allows pybot to respond to various events that may occur in your Slack workspace.
  • Slash Commands - this allows a user to invoke various commands from any channel in your workspace to interact with pybot.
  • Interactive Components - this allows various options to be exposed when right clicking on a message, or, when the bot presents various user elements that can be interacted with, instructs Slack on where to send the results for such interactions.

High level steps for configuring each of these can be found in the following sub-sections; note that you don't need to necessarily configure all of these, it all depends on what areas of pybot you're wanting to play with.

Event Subscriptions

You can follow the instructions (and read helpful related information) on the Events API page on Slack to setup event subscriptions. When configuring your events URI; make sure you pass in the Base-URI that pybot is listening on followed by the text /slack/events. For example:

https://123_random_code_321.ngrok.io/slack/events

Additional setup may be needed depending on the type of events pybot is subscribing to. For example, in order to work on the app's functionality on a team_join event, you need to:

  • Add team_join to workspace event
  • Make sure greetings channel exists and ensure the app is invited to the channel
  • Add necessary OAuth scopes to the app e.g. users:read, chat:write, etc.

In the section which says "Subscribe to events on behalf of users", you must add the following events:

Event Name Required OAuth Scope
member_joined_channel channels:read or groups:read
message.channels channels:history
message.groups groups:history
message.im im:history
team_join users:read

Slash Commands

You can follow the instructions (and read helpful related information) on the Enabling interactivity with Slash Commands page on Slack to setup pybot slash commands. When configuring a Slash command, make sure you configure the request URL to match the Base-URI that pybot is listening on followed by the text /slack/commands. For example:

https://123_random_code_321.ngrok.io/slack/commands

You'll use the same URI for each command. Here's a table listing of currently supported commands along with some suggested configuration text:

Command Description Usage Hint
/lunch find lunch suggestions nearby <zip code> <distance in miles>
/mentor request mentoring
/mentor-volunteer offer to mentor others
/repeat parrot canned messages <10000
/report report something to the admins
/roll roll x dice with y sides
/ticket submit ticket to admins (text of ticket)

👋 IMPORTANT!

The /lunch command requires a valid Yelp API token stored in the YELP_TOKEN environment variable. See https://www.yelp.com/developers/faq

Similarly, the /mentor and /mentor-volunteer commands require access to an Airtable environment with a specific configuration. If you're planning on working with the mentor functionality please reach out to the #oc-python-projects channel for help getting set up.

Interactive Components

You can follow the instructions (and read helpful related information) on the Handling user interaction in your Slack apps page on Slack to setup Slack interactive component configuration. When configuring the request URL, you'll want to set it to the Base-URI that pybot is listening on followed by the text /slack/actions. For example:

https://123_random_code_321.ngrok.io/slack/actions

You'll also want to make sure to configure the report message action with the following parameters:

Name Description Callback ID
Report Message Report this message to admins report_message

License

This package is available as open source under the terms of the MIT License.

Notes

Option 1 - Create your own Slack workspace to use for testing. Follow this guide

Start the application with WebSockets instead of HTTP for better development experience? Requires the use of the SLACK_APP_TOKEN. Would need to set an environment variable to determine if we were in development or staging/production.

Database to store history of events or just use logging? Probably best to use a database to store history of requests and responses? Easier to track interactions that way.

Utilizing FastAPI allows us to take advantage of things like Pydantic, inherent typing, models, and a better handler for the HTTP requests themselves.

Utilizing FastAPI and Slack-Bolt.

All the interactive elements of this bot were built using the Slack Block Kit Builder. The example JSON for each interactive element can be found in the modules/slack/blocks/block_kit_examples folder.

operationcode-pybot's People

Contributors

aaron-junot avatar adeola-adesoba avatar allenanthes avatar apex-omontgomery avatar ashtemp avatar chynh avatar cskinner74 avatar dependabot-preview[bot] avatar dependabot[bot] avatar garyray-k avatar harithesolo avatar judsonstevens avatar kylemh avatar mdeanlindsay avatar ptrstr avatar rochellelynn-programmer avatar techytushar avatar vaishnavi-cyber-blip avatar vatsalsharma376 avatar vyaspranjal33 avatar wendeee 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

operationcode-pybot's Issues

Slack Invite Error should go to Ops channel instead of moderator channel

When an error inviting a user to slack is encountered, it's really up to the staff to handle that rather than the moderators. The error is currently defined here

"channel": MODERATOR_CHANNEL,

Instead, it should go to the Ops channel, which is currently named #oc-ops. I don't think this currently has any bot messages go to it, so it will need to be added here

TICKET_CHANNEL = os.environ.get("TICKET_CHANNEL", "oc-tech")

The default should be oc-ops because that's its current name. We'll set the actually channel ID in the production environment variables.

Feature request: Survey Slash Command

Create new / command on Pybot called “survey-member”. The command should send a DM explaining to the user why we collect the information that we do and beg them to click a link which navigates to “survey” page.

This is related to issue OperationCode/back-end#347 in the back-end repo.

Integrate town-crier with pybot

Right now, town-crier is a separate project from pybot that works off of Airtable.

We'd need to integrate town-crier, with some associated backend work to add the announcements and cronjob functionality.

PR bot for frontend

This is a pretty big one, but working with @dmarchante to get this done.

  1. Incorporate sirbot github plugin to pybot
  2. Create a service class that routes events from the github plugin
  3. Setup logic within service class for pull-requests in frontend to check for component changes
  4. BUSINESS LOGIC: in component folder: if **/*.js or **/*.css but not *.test.js or not *.stories.js then we post a comment telling user to verify something.

It appears that this is the event we want to use:
https://developer.github.com/v3/activity/events/types/#pullrequestevent

the payload example can be seen here:
https://developer.github.com/v3/activity/events/types/#webhook-payload-example-25

it looks like there's an action value and we would like opened

Also looks like they have an endpoint:
https://developer.github.com/v3/pulls/#list-pull-requests-files

which returns a list of file json objects:

[
  {
    "sha": "bbcd538c8e72b8c175046e27cc8f907076331401",
    "filename": "file1.txt",
    "status": "added",
    "additions": 103,
    "deletions": 21,
    "changes": 124,
    "blob_url": "https://github.com/octocat/Hello-World/blob/6dcb09b5b57875f334f61aebed695e2e4193db5e/file1.txt",
    "raw_url": "https://github.com/octocat/Hello-World/raw/6dcb09b5b57875f334f61aebed695e2e4193db5e/file1.txt",
    "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/file1.txt?ref=6dcb09b5b57875f334f61aebed695e2e4193db5e",
    "patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"
  }
]

initial issue is here:

OperationCode/front-end#14

For now instead of using a pre-commit hook we can deal with post-PR hooks.

Add button to #greetings for a 1:1 conversation

Right now, our bot has a button to claim a new user for greeting.

I would like to add a second button, for a user to also claim a 1:1 conversation (a DM)

So, next to "I will greet them!", would be "I will DM them!"

Feature: random quote slash command

Description

I'd love to be able to have a list of random quotes so I can have them post in the channel.

Maybe even include a fuzzy text search to find ones that match?

Purpose

This would be interesting to get this.

#Greetings channel needs a "I Will DM" button

New functionality request
Please create an "I Will DM" button for the Outreach Team to mash once they DM a new member.

Why
Outreach Team will be initial POC's for Operation Code. This reduces dropout rate, increases retention and engagement, and provides a link between the new member and mentors.

How This Will Be Used
Greeters can still mash the "I Will Greet" button and greet the new members in #general but the Outreach Team can mash the "I Will DM" button so engagement is increased. A reminder in the #greetings channel is set for all new members at the 30 day mark to follow up as well.

Slack Command !search

!search how to print line java will look through stackoverflow or google for results and then post a link.

CI/ CD alerting

When a new ECS instance is correctly deployed and receiving traffic send message to #oc-python-projects informing of the status change.

Move off Travis onto CircleCI

Copying from front-end issue, since we're not cool enough for @jack-robs to open the issue here.

Move off of Travis onto CircleCI since Travis is barely a company anymore post-layoffs

Feature: Repeated text commands

Description

Slash command that can be configured on a workspace level:

  1. Various text that when requested will paste a message in that channel.

Ex:

/repeat ask
Will paste a generic (non-rude) text message with link to this: http://sol.gfxile.net/dontask.html

/repeat 10000
Will paste this link when a text message
https://xkcd.com/1053/

Make this configurable by workspace. With a template that is automatically generated.

Purpose

Reduce friction from people who get frustrated at others, and codify certain situations.

Rate Limit on Mentor Requests

There exists a possibility that someone could put in a ridiculous amount of mentor requests, pinging the same mentors over and over again. Mentors would possibly then be encouraged to just mute the #mentors-internal channel, which would stop legitimate mentor requests from being answered in a timely fashion.

A rate limit should exist so that a given user can only put in a limited amount of mentor requests in a given time period. 3x per month was suggested, so let's start with that and see how it goes.

Acceptance criteria:

When attempting to put in too many mentor requests in a month, the user should see a message from slackbot informing them that they've put in as many mentor requests as allowed until the time when they'll be allowed to put it in again. For example:

Error: you have put in too many mentor requests. You will be allowed to submit another mentor request on June 15, 2020

The above message would be if the first of 3 mentor requests was put in on May 15, 2020.

Slash command for requests

/ticket

should open a slack interactive form that get's processed and piped to an admin/ tech lead channel.

This form has fields that allow the user to indicate the request type.

email
request type (dropdown?)
details

The new in chat request has a way of of individuals claiming the ticket, and buttons for:
in progress
complete
waiting user request
Which update like the other in slack messages.

The goal of this ticket is to make request credentials, email accounts, and other administrative things more organized.

Feature: archive silent channels

Description

  1. Archive channels that have had 30 days of no activity and are public.
  2. No activity means no new messages.
  3. 24 hours prior the channel will have a warning with an explanation.
  4. This will be checked daily
  5. The warning will not affect or stop the archiving
  6. This will require administrative action and is reliant on Issue #3

Purpose

This is to clean up the clutter for new people when they are looking for channels.

Mentor Enrollment Form

The Mentor Request form is available via the command /mentor. It would be nice to have the mentor enrollment form also be available via Slack. Perhaps it could be /mentor-enroll or /mentor enroll. In any case, it should have the same fields as the current enrollment form (https://op.co.de/mentor-enrollment) and should link up to airtable the same way.

Auto-Invite to Location Based Channels on Join

Relative Priority: MEDIUM

As a user, I want to autojoin a Slack channel corresponding to my location when I join, so I know there is a local community associated with Operation Code that I can interact with.

Product Requirements

  • (MVP) Users on signup who have zipcodes associated with the DC area autojoin #dc.
  • (Users on signup who have zipcodes associated with the NYC area autojoin #nyc.

Technical Requirements

  • Associate groupings of zipcodes with specific slack channels.
  • Ex. #dc - 20001, 20002, 20003, 20004, 20005, 20006, 20007, 20008, 20009, 20010, 20011, 20012, 20015, 20016, 20017, 20018, 20019, 20020, 20024, 20032, 20036, 20037, 20045, 20052, 20053, 20057, 20064, 20202, 20204, 20228, 20230, 20240, 20245, 20260, 20307, 20317, 20319, 20373, 20390, 20405, 20418, 20427, 20506, 20510, 20520, 20535, 20540, 20551, 20553, 20560, 20565, 20566, 20593.
  • Use geolocation based on the different areas and have each of those leaders determine how many miles is close enough.

Engagement Leaderboards

Have a hiscores command to display slack and github metrics.

This feature would:

  • Award points to users for certain activities in slack. (1 point for messaging, 5 points for introducing new members, etc)
  • Award points for GitHub actions (Merged PR - 50 points, comment - 1 point, etc)
  • Display a rolling monthly hiscore list. It could also give achievements for "Most Helpful - Most active in #help" etc.

This was just an idea for a feature we could hypothetically have and Conrad asked me to make the issue a few weeks back.

daily-programmer pin manager bot

See this thread for background

Slack channels can only have 100 pins. But we pin all problems in the #daily-programmer channel. @kevinkiklee has to manage these manually.

Create a bot that when it runs

  1. Unpins the 100th pinned post in #daily-programmer (if there is one)
  2. Adds a link to it along with its title (there's a standard format we use if you look at them) to some "Operation Code Daily Programmers" list somewhere online - may be a github pages repo, a wiki, or a web page
  • Don't do that if this post is already linked
  • We would want to do an initial scan through all posts in the channel and see if we can auto-detect them and put them up there.

As many daily programmers come from places like Hacker Rank and Leetcode, we don't want to post the problem itself outside of slack - that would violate copyright, just link to the post.

Feature: Update Mentor matching

Description

Improve mentor alerts in the mentor channel to give more context.

  1. If less than 3 values found for the mentor matched use the partial matching.
  2. Display requested mentor
  3. The username is determined by email, when a email-> username value is not found this provides an unclear value, make this better.

Purpose

Provide a better experience for mentors.

Feature: Setup Staging

Description

I'd love to be able to hook this into CI/CD for a staging on PRs or a specific branch tag. Have it connected to a test system and then be able to test things immediately.

Purpose

Become more lazy, I mean more productive.

Daily Programmer Management

Store daily programmer in some format. Ping general with the new daily event. Provide a reference to others so they can do them later.

Feature: Monitoring/ logging

Description

We have access to watchtower and sentry. We can be using these for better monitoring and logging.

  1. Monitoring of specific scenarios through use of sentry.
  2. Hook into Watchtower or something else to have easy access to the logs.

Purpose

Post event trouble shooting, and alerting of issues.

Match Auth tokens to api names

We use:

# APP_TOKEN=
# SLACK_TOKEN=
# SLACK_VERIFY=
# SLACK_BOT_ID=
# SLACK_BOT_USER_ID=

The api uses:
image

Make it easier for someone to make a test slack and put the correct tokens in.

Feature: Properly manage multiple token scopes

Currently we have actions that require either a bot or app token. Some actions will require even higher permissions (admin).

We need to come up with a way to properly manage these to ensure that a failure of one token doesn't fail the whole application.

Feature: Improve /here command

Description

Currently the /here message is pretty basic but it works.

image

Currently we send a message to all users subscribed to the channel using a channel message and a thread for the indidivual users. This change would modify the behavior so that we can either use elevated @here @channel or a new group for the channel @channel_group which contains the users.

Purpose

Provide channel and community moderators a more organic way to interact with their users.

Auto-Invite to Military or Veteran Related Channels on Join

Cross link between back end issue 47.

The back end optionally passes the military status info to pybot, pybot has an association of military status to channel ID, and submits that with the optional parameters of the undocumented slack api call users.admin.invite called here with those slack channel ids if present.

Additional information is presented in this SO post.

A warning should be noted that this feature may be deprecated in favor of the priced (Plus/Enterprise) slack APIs in the future.

Feature: Workspace level feature configuration

Description

  1. Allow Workspace administrators to configure their workspace configurations for various tasks
  2. This change would be the first step in allowing the application to support multiple workspaces.

An example:
On workspace XXXXXX, we want to archive channels after YYYY days of inactivity.

Purpose

In addition to configuration, this would provide the ability to toggle on or off features.

Extract data for most replied to topics

As a request from the Marketing Team, we would like to extract the most replied to topics within a channel on a monthly basis for inclusion in our newsletter and also for public engagement purposes. There may be an inconclusive data extract if users do not reply to a thread, but reply as a single post.

Data extraction via top key words may also be used. Thank you all who contribute!

Dependabot can't resolve your Python dependency files

Dependabot can't resolve your Python dependency files.

As a result, Dependabot couldn't update your dependencies.

The error Dependabot encountered was:

The "black" dependency specifies the "allows-prereleases" property, which is deprecated. Use "allow-prereleases" instead.
Creating virtualenv operationcode-pybot-Fb03ptpD-py3.8 in /home/dependabot/.cache/pypoetry/virtualenvs
Updating dependencies
Resolving dependencies...

[PackageNotFound]
Package colorama (0.4.1) not found.

If you think the above is an error on Dependabot's side please don't hesitate to get in touch - we'll do whatever we can to fix it.

View the update logs.

Make slash commands work in private messages

Currently when a user tries to do a slash command in a private channel or a channel the bot doesn't have access to the response from slack is that the channel cannot be found.

This is due to the dragons in the api.

image

Auto-Reply Functionality for Unformatted Code

Problem:

We tend to have people posting often who don't know the three main ways to format code on slack. A bot to help them do this properly would save everyone some time and annoyance. Plus it should be fun to code.

This bot will activate when there is a post where a subset of the lines contains something that looks like code but is not formatted as such

So how to determine if something looks like code? Two possible approaches.

  1. Heuristically. There are libraries out there that auto-detect language. Presumably some of the same processes can be used to detect whether something is code at all. Example of something that does this: highlight.js

  2. ML. This is actually a pretty decent use case for something like a tensorflow classifier. And we could train it off of the actual operation code logs!

repeat command should be able to 'at' a user

The repeat command should have the ability to 'at' a designated user, not just the person who called it
Existing
image

Proposed
/repeat channels @someone

should produce:

@someone: check out the channel guide (sent by: @sender)

Feature: Job Announcement Bot

Description

An announcement that pops up in the job-board Slack channel when a new job is added to the 'Featured Jobs' section of the site.

Purpose

Make members in the Slack aware of new job opportunities; but automate it because Kelly is lazy/garbage.

Feature: Operation Code Challenge

Description

Slash command (using repeat? ) to list the operation code challenge people who completed the challenge along with a description of it.

Change resources.yml to resources page

The Operation Code Resources Page is now live and functional. We should link to that from the /repeat resources command.

"link": "https://github.com/OperationCode/resources_api/blob/master/resources.yml",
"title": "A big list of resources",
"pretext": "Would you like some resources.yml?",

This should link to https://operationcode.org/resources

It should be titled "A searchable database of learning resources"

Pretext should be "Would you like some learning resources?"

Mentor Partial Matching Broken

Bug Report

What is the current behavior?

When a new mentor request comes in with a combination of skillsets that aren't met by any mentors the bot no longer displays a list of partial matches.

What is the expected behavior?

A list of mentors partially matching the requested skillsets should be displayed.

Screenshots

image

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.