Giter Club home page Giter Club logo

showrenamer's People

Contributors

c-eg avatar chris-sutcliffe avatar harrytaylordev avatar shrimpguard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

showrenamer's Issues

[Bug] Rename fails if show name includes characters not supported by files

Describe the bug
When trying to rename files, if the renamed show includes any characters not supported by files, the rename will fail.
See here for a list of unsupported characters.

Expected behavior
The unsupported characters will either be removed or replaced by ones that are supported by files.

Desktop (please complete the following information):
OS: Windows 10

Additional context
Might be good to have a function, checking the name of the show and the name of the episode if it's a tv show, to return an acceptable name for the file to be renamed to.

Fix user having to install JDK 17 to run app

Currently the user must download Amazon Corretto JDK 17 in order to use the application.

To fix this we should create a module-info.java, which allows us to easily package the application into an installer,

Update the look of the page navigation buttons

The page navigation buttons (currently Rename and Settings) don't look great. We should update the styling for these to make them look better.

Currently not sure how this should look like, open for suggestions.

Move properties loading logic

Currently the properties loading logic is used where needed, e.g. RenameController to load the api key for the movie database api. This functionality to load the property should be moved to a separate class so it can be used anywhere, and is easier to test.

[Feature] Add Command Line Interface (CLI) support

Is your feature request related to a problem? Please describe.
If you do not want to use the GUI, there's no way to use the app.

Describe the solution you'd like
A way to use the app from CLI.

Additional context
A discussion is needed before any work is done.

[Feature] Improve Readme

Is your feature request related to a problem? Please describe.
Readme isn't very helpful setting up the project once forked, or downloading the app to use.

Describe the solution you'd like
Write a clear description of how to setup the project in your own envrionment.
Write a clear description of how to use the app, with a screenshot or two.

Fix year matching regex

Currently a test is failing testMatchYearContainingYearInTitle.

It fails to capture the correct year if the movie contains a year in the title.

e.g. some.random.movie.2012.2010.1080p.bluray.x264 would match as 2012 of the correct match 2010

Add file type filtering

File type filtering functionality should be implemented so that when files are added, it will only add the files that are in the supported types.

A section in the settings page navigation will need to be added to select which files types are supported. There should be the following:

  • checkbox to select whether to use the file type filtering (default = false)
  • some form selection to select which files types are allowed.

Refactor of code needed

The current code base is badly written and not abstracted enough, it needs to be split down into seperate classes to simplify everything.

This will result in much cleaner code, and allow CLI support to be implemented as well as having an option to implement multiple APIs for show data.

Need to refactor code using TMDB API

The current code for using the API is very slow. It should be refactored to make it more efficient and reduce the number of unnecessary API calls.

I believe the issue is in the getSuggestedNames() function in RenameController.java, starting line 116.

Allow user to specify suggestion format

The user cannot customise the suggestion format, currently it is:

  • Movie: "{Movie Title} ({Year})"
  • Tv Series: "{Tv Series Title} - S{Season Number}E{Episode Number} - {Episode Title}"

Implement the backend functionality to enable the user to select the rename format.

[Feature] Add anime support

Is your feature request related to a problem? Please describe.
User can't automatically rename any anime

Describe the solution you'd like
Add support for anime

Create Settings Page

Create a menu on the rename page, adding the following text, along with an image:

  • Rename
  • Settings

For now, the settings page can remain empty, with the same background styling as the rename page.

Implement folder renaming

Movie: "{title} ({year})"

For tv shows, it should rename the folder to the title of the show, then create sub folders for each season present, e.g. Season 1, Season 2

[Feature] Settings page

Is your feature request related to a problem? Please describe.
If the user wants a different format for shows other than 'Movie (Year)' or 'Show - SXXEXX - Episode Name' they will still have to manually rename.

Describe the solution you'd like
Add a new page called settings, which would allow you to customise the format you would like a Movie and a Show to output as.

Getting rename suggestions causes lists to re-order

Currently the way the list views are set up to listen to events from the HashMap cause the lists to re-order when getting rename suggestions. This is because hash maps do not have ordering, and the map gets update, causing the listener to trigger, updating the list views.

[Feature] App Icon

Is your feature request related to a problem? Please describe.
There is currently no icon for the application.

Describe the solution you'd like
An icon made for the application, preferably multi-coloured.

[Bug] Rename fails when adding more than 1 source

Describe the bug
If you add more than one source of files to rename, the rename will not work. Causing an IndexOutOfBounds Exception.

To Reproduce
Steps to reproduce the behavior:

  1. Add sauce folder
  2. Add another sauce folder
  3. Click Get Rename Suggestions
  4. Click Rename ALL
  5. See Error

Expected behavior
Renames all files is seperate folders

Additional context
It does rename the first source folder added but not other source folders added.

Error:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
	at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787)
	at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Node.fireEvent(Node.java:8885)
	at javafx.scene.control.Button.fire(Button.java:203)
	at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
	at com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
	at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Scene$MouseHandler.process(Scene.java:3890)
	at javafx.scene.Scene.processMouseEvent(Scene.java:1885)
	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2618)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:409)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:299)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:447)
	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:412)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:446)
	at com.sun.glass.ui.View.handleMouseEvent(View.java:556)
	at com.sun.glass.ui.View.notifyMouse(View.java:942)
	at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
	at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:273)
	at com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
	at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1784)
	... 46 more
Caused by: java.lang.IndexOutOfBoundsException: start 0, end -1, length 200
	at java.base/java.lang.AbstractStringBuilder.checkRange(AbstractStringBuilder.java:1805)
	at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:686)
	at java.base/java.lang.StringBuilder.append(StringBuilder.java:212)
	at uk.co.conoregan.showrenamer.controller.RenameController.renameAll(RenameController.java:174)
	... 58 more

[Feature] Checkbox to scan for subfolders

Is your feature request related to a problem? Please describe.
Having to manually select every folder can be annoying, adding a checkbox to include sub-folders in the initial directory given would solve this.

Describe the solution you'd like
A checkbox next to the directory dialog button, which if checked would include sub-folders when selecting the directory. This could be done with recursion.

[Feature] Rename selected button

Is your feature request related to a problem? Please describe.
Can't rename a single show in the list.

Describe the solution you'd like
Select the show you would like to rename, click rename show, renames only the selected show and none of the others.

Add loading animation when Get Suggestions is clicked

When the application is making requests to the movie database api, it doesn't update the ui until all results are retrieved, and a suggested is returned for each. This means there could be a fairly long delay for the user with no feedback.

To fix this, we should add an animation so that the user knows the application is working and getting the suggestion results for them.

The loading animation should go over the Suggested Titles list view.

[Feature] Add subtitle download page

Is your feature request related to a problem? Please describe.
Searching for subtitles for a large amount of shows is extremely tedious.

Describe the solution you'd like
A page to read in a directory of shows (like on the rename page) and list all shows. Each show would have a checkbox to make that would be set to checked by defualt. If a checkbox is ticked it will download the subtitles for that show. And buttons at the bottom to get all subtitles or get a subtitle for a selected show (again like on the rename page). An output directory would need to be specified here too.

"No result found"

Clicking on Get Suggestions results in

$> java -jar show-renamer-1.3.0.jar
Nov 25, 2023 12:09:28 PM com.sun.javafx.application.PlatformImpl startup
WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @6ced7109'
[JavaFX Application Thread] INFO uk.co.conoregan.showrenamer.ShowRenamerApplication - Show Renamer successfully started.
[ForkJoinPool.commonPool-worker-2] INFO uk.co.conoregan.showrenamer.suggestion.FileSuggestionProvider - No result found for title: <my title>

Not sure if I installed the prerequisite JDK properly. Maybe the app could detect it and if it's not there give some kind of notice.

Add GNU GPLv3 comment at top of each file

To make sure the license is applied to all code in the repo, according to GNU. Attatch this to the top of each file:

/* 
 * This file is part of ShowRenamer.
 * 
 * ShowRenamer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ShowRenamer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ShowRenamer.  If not, see <https://www.gnu.org/licenses/>. 
 */

[Bug] Files are not renamed if files are added via source, then some are removed

Describe the bug
Error when trying to rename files when you add some via source, then remove some.

To Reproduce
Steps to reproduce the behavior:

  1. Add files via source
  2. Remove some of the files from the list on the left
  3. Get Rename Suggestions
  4. See error

Expected behavior
Should still rename after some files were removed

Additional context
Error stack trace:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
	at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787)
	at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Node.fireEvent(Node.java:8885)
	at javafx.scene.control.Button.fire(Button.java:203)
	at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
	at com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
	at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Scene$MouseHandler.process(Scene.java:3890)
	at javafx.scene.Scene.processMouseEvent(Scene.java:1885)
	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2618)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:409)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:299)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:447)
	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:412)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:446)
	at com.sun.glass.ui.View.handleMouseEvent(View.java:556)
	at com.sun.glass.ui.View.notifyMouse(View.java:942)
	at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
	at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:273)
	at com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
	at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1784)
	... 46 more
Caused by: java.lang.IndexOutOfBoundsException: Index 8 out of bounds for length 8
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
	at java.base/java.util.Objects.checkIndex(Objects.java:373)
	at java.base/java.util.ArrayList.get(ArrayList.java:427)
	at com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89)
	at uk.co.conoregan.showrenamer.controller.RenameController.renameAll(RenameController.java:164)
	... 58 more

Notify user when renaming has completed

Currently when the user clicks the Save All button to save all suggestions, there is no feedback to the user to say it was successful - it just clears the lists. We should implement some form of feedback to say the renaming was successful.

Make UI only allow actions based on state

Stage 1 - When no files are loaded:

  • Disable all buttons, apart from the "Add Folder" button
  • Change css to indicate buttons and sections are not currently available

Stage 2 - When at least 1 file is loaded:

  • Enable "Get Suggestions" button
  • Change css to indicate the "Get Suggestions" button and section is now available

Stage 3 - When suggestions have been retrieved:

  • Enable "Save All" button
  • Change css to indicate the "Save All" button and section is now available
  • Change css to indicate the "Get Suggestions" button is no longer available

[Feature] App themes

Is your feature request related to a problem? Please describe.
Different people like diferent colour schemes/themes. Such as light mode and dark mode.

Describe the solution you'd like
Add an option in the settings page to select a theme for the application. Have a seperate css file for each theme. Could add support for custom themes too in the future.

Fix title matching regex

Currently a test is failing testMatchTitleContainingYear.

It fails to capture the full title of the movie if the title also contains a year.

e.g. some.random.movie.2012.2010.1080p.bluray.x264 would match as some.random.movie instead of the correct match some.random.movie.2012

[Feature] Font for app

Is your feature request related to a problem? Please describe.
The default font for JavaFX is basic

Describe the solution you'd like
A new modern font

[Feature] Two buttons to clear ListViews

Is your feature request related to a problem? Please describe.
2 buttons to help the user clear the list view of Shows they do not want to rename. 1. Can remove one show. 2. Clear all shows.

Describe the solution you'd like
Two buttons underneath the lists, one to clear a single show from the left list, one to clear all shows from the left list. The right list should be updated correctly after this is done.

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.