From b0ab9b1369a7092a47dc5cf1e81c56d645197531 Mon Sep 17 00:00:00 2001 From: Oktay Sen Date: Wed, 6 Feb 2019 14:26:01 +0000 Subject: [PATCH] Demo 1 (#87) * Added android project * Added travis config file * travis now tests the server at the correct directory * Added build status image to main README.md * I34 (#40) * Added travis config file * travis now tests the server at the correct directory * Added build status image to main README.md * Fixed server tests in travis * Added beta branch build status to README.md * I32 (#36) * Set up server npm project * Implemented basic TCP socket server * Added RobotConnection tests * Added README.md * Added note about Prettier. * I35 (#42) * added directory for robot software * added toddler * Removed root .idea * create MOTOR_FORWARD variable * I37 (#48) * Added Firebase Functions to server * Moved Firebase project to root and reset changes made to server project * Added README.md and tidied firebase.json * Added Content to README.md * Changes to index.js * Final Updates to structure and README * Removed the server directory * Removed the server directory (#50) * Added jest testing to firebase functions. * Jest temporarily passes without tests. * I51 (#52) * Removed the server directory * Added jest testing to firebase functions. * Jest temporarily passes without tests. * Fixed travis deployment not working * I51 (#53) * Removed the server directory * Added jest testing to firebase functions. * Jest temporarily passes without tests. * Fixed travis deployment not working * Potential fix for firebase deployment * Fixed firebase functions deployment on Travis * Added master firebase project to travis deploy * I55 (#58) * Removed firebase folder * Removed firebase functions deployment from travis.yaml * Random IntelliJ changes * I56 (#67) * move robot forward using both motors * add skeleton class for detecting line * create line follower object in toddler * try to fix but everything breaks * add detectLine * makes BOB sidestep * detect colour * can differentiate between black line and white paper * I45 (#57) * move robot forward using both motors * add skeleton class for detecting line * create line follower object in toddler * try to fix but everything breaks * add detectLine * makes BOB sidestep * detect colour * can differentiate between black line and white paper * move but can't stay on line * use 2 colour sensors * Merge branch 'i56' of https://github.com/Assis10t/assis10t into i56 Conflicts: ev3/detectLine.py * stops bob only turning right * follow line decently * make code nicer * I58 (#69) * Removed firebase folder * Removed firebase functions deployment from travis.yaml * Random IntelliJ changes * Made initial hello world server * Added more packages * Minor change to README * Minor change to README * Basic implementation of a CRUD server with mongodb * Added Bonjour Publisher and Client * added bonjour * Robot comms teset * WIP makefile * Re-added package-lock.json * Robot turns on when button pressed * Android can now find server via zeroconf * Added test mode for when disconnected from robot * Refactored ServerConnection * Updated server name in android * Added turn off on * Added Feedback * Added Off/On Switch * Final touches * I66 (#70) * start detect marker * add stop method * add runner on separate thread * bOb stops when detecting green line * beobe stops after 3 lines man * I71 (#72) * start detect marker * stop on blue * I60 Connected Android to server (#74) * Removed firebase folder * Removed firebase functions deployment from travis.yaml * Random IntelliJ changes * Made initial hello world server * Added more packages * Minor change to README * Minor change to README * Basic implementation of a CRUD server with mongodb * Added Bonjour Publisher and Client * added bonjour * Robot comms teset * WIP makefile * Re-added package-lock.json * Robot turns on when button pressed * Android can now find server via zeroconf * Added test mode for when disconnected from robot * Refactored ServerConnection * Updated server name in android * Added turn off on * Fixed minor things * App can display list of items * Re-added addItem and getItems * Fixed app not connecting to server * Added ability to refresh list of items * Implemented adding order on android * Adding order now removes the items in it from the database * I76 (#79) * start detect marker * stop on blue * added function for sideways movement * I78 Basic authentication (#83) * Login works on the server & mini website. * Implemented Android login. * Added zeroconf bypass * Added back button to LoginActivity * I81 Bypass zeroconf (#84) * Login works on the server & mini website. * Implemented Android login. * Added zeroconf bypass * addOrder now starts moving the robot (#85) * I58 (#86) * Removed firebase folder * Removed firebase functions deployment from travis.yaml * Random IntelliJ changes * Made initial hello world server * Added more packages * Minor change to README * Minor change to README * Basic implementation of a CRUD server with mongodb * Added Bonjour Publisher and Client * added bonjour * Robot comms teset * WIP makefile * Re-added package-lock.json * Robot turns on when button pressed * Android can now find server via zeroconf * Added test mode for when disconnected from robot * Refactored ServerConnection * Updated server name in android * Added turn off on * Added Feedback * Added Off/On Switch * Final touches * Updated Website * additional changes * Added Input Verification * Merge beta * Fixed merge issues and other bugs --- .DS_Store | Bin 0 -> 6148 bytes .gitignore | 1 + .idea/assis10t.iml | 12 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .travis.yml | 10 + .vscode/.ropeproject/config.py | 114 + README.md | 5 + android/.gitignore | 11 + android/.idea/codeStyles/Project.xml | 35 + android/.idea/codeStyles/codeStyleConfig.xml | 5 + android/.idea/gradle.xml | 18 + android/.idea/misc.xml | 44 + android/.idea/runConfigurations.xml | 12 + android/.idea/vcs.xml | 6 + android/app/.gitignore | 1 + android/app/build.gradle | 41 + android/app/proguard-rules.pro | 21 + .../bobandroid/ExampleInstrumentedTest.kt | 24 + android/app/src/main/AndroidManifest.xml | 28 + .../github/assis10t/bobandroid/Application.kt | 19 + .../assis10t/bobandroid/LoginActivity.kt | 61 + .../assis10t/bobandroid/MainActivity.kt | 161 + .../assis10t/bobandroid/ServerConnection.kt | 186 + .../bobandroid/pojo/GenericResponse.kt | 3 + .../bobandroid/pojo/GetItemsResponse.kt | 3 + .../github/assis10t/bobandroid/pojo/Item.kt | 6 + .../assis10t/bobandroid/pojo/LoginRequest.kt | 6 + .../assis10t/bobandroid/pojo/LoginResponse.kt | 6 + .../github/assis10t/bobandroid/pojo/Order.kt | 6 + .../bobandroid/pojo/RegisterRequest.kt | 6 + .../io/github/assis10t/bobandroid/utils.kt | 36 + .../drawable-v24/ic_launcher_foreground.xml | 34 + .../res/drawable/ic_launcher_background.xml | 74 + .../main/res/drawable/ic_send_black_24dp.xml | 9 + .../src/main/res/layout/activity_login.xml | 50 + .../app/src/main/res/layout/activity_main.xml | 31 + .../main/res/layout/fragment_shop_item.xml | 25 + .../app/src/main/res/menu/menu_toolbar.xml | 11 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2963 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4905 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2060 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2783 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4490 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6895 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6387 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10413 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9128 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15132 bytes android/app/src/main/res/values/colors.xml | 9 + android/app/src/main/res/values/strings.xml | 3 + android/app/src/main/res/values/styles.xml | 11 + .../assis10t/bobandroid/ExampleUnitTest.kt | 17 + android/build.gradle | 27 + android/gradle.properties | 15 + android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + android/gradlew | 172 + android/gradlew.bat | 84 + android/settings.gradle | 1 + ev3/detectMarking.py | 13 + makefile | 59 + robot_software/__init__.py | 0 .../__pycache__/follow.cpython-36.pyc | Bin 0 -> 2041 bytes robot_software/follow.py | 101 + robot_software/follow.pyc | Bin 0 -> 2678 bytes robot_software/followLineServer.py | 155 + robot_software/lineFollower.py | 30 + robot_software/mongo_client.py | 141 + server/.gitignore | 1 + server/.prettierrc | 10 + server/README.md | 33 + server/db.js | 37 + server/index.js | 138 + server/model.js | 132 + server/package-lock.json | 5882 +++++++++++++++++ server/package.json | 31 + server/public/index.html | 116 + server/public/md5.min.js | 510 ++ server/utils.js | 34 + 83 files changed, 8917 insertions(+) create mode 100644 .DS_Store create mode 100644 .gitignore create mode 100644 .idea/assis10t.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .travis.yml create mode 100644 .vscode/.ropeproject/config.py create mode 100644 android/.gitignore create mode 100644 android/.idea/codeStyles/Project.xml create mode 100644 android/.idea/codeStyles/codeStyleConfig.xml create mode 100644 android/.idea/gradle.xml create mode 100644 android/.idea/misc.xml create mode 100644 android/.idea/runConfigurations.xml create mode 100644 android/.idea/vcs.xml create mode 100644 android/app/.gitignore create mode 100644 android/app/build.gradle create mode 100644 android/app/proguard-rules.pro create mode 100644 android/app/src/androidTest/java/io/github/assis10t/bobandroid/ExampleInstrumentedTest.kt create mode 100644 android/app/src/main/AndroidManifest.xml create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/Application.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/LoginActivity.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/MainActivity.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/ServerConnection.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/pojo/GenericResponse.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/pojo/GetItemsResponse.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/pojo/Item.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/pojo/LoginRequest.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/pojo/LoginResponse.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/pojo/Order.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/pojo/RegisterRequest.kt create mode 100644 android/app/src/main/java/io/github/assis10t/bobandroid/utils.kt create mode 100644 android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 android/app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 android/app/src/main/res/drawable/ic_send_black_24dp.xml create mode 100644 android/app/src/main/res/layout/activity_login.xml create mode 100644 android/app/src/main/res/layout/activity_main.xml create mode 100644 android/app/src/main/res/layout/fragment_shop_item.xml create mode 100644 android/app/src/main/res/menu/menu_toolbar.xml create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/values/colors.xml create mode 100644 android/app/src/main/res/values/strings.xml create mode 100644 android/app/src/main/res/values/styles.xml create mode 100644 android/app/src/test/java/io/github/assis10t/bobandroid/ExampleUnitTest.kt create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.jar create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100644 android/gradlew create mode 100644 android/gradlew.bat create mode 100644 android/settings.gradle create mode 100644 ev3/detectMarking.py create mode 100644 makefile create mode 100644 robot_software/__init__.py create mode 100644 robot_software/__pycache__/follow.cpython-36.pyc create mode 100644 robot_software/follow.py create mode 100644 robot_software/follow.pyc create mode 100644 robot_software/followLineServer.py create mode 100644 robot_software/lineFollower.py create mode 100644 robot_software/mongo_client.py create mode 100644 server/.gitignore create mode 100644 server/.prettierrc create mode 100644 server/README.md create mode 100644 server/db.js create mode 100644 server/index.js create mode 100644 server/model.js create mode 100644 server/package-lock.json create mode 100644 server/package.json create mode 100644 server/public/index.html create mode 100644 server/public/md5.min.js create mode 100644 server/utils.js diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5b642aa54d15b40bf01252c789b63c47f9eab925 GIT binary patch literal 6148 zcmeHK&2G~`5S~p#x()(zKx&V^AaRIL+EQ8xA(@aKdO$)L!2wWeV?!;u-pY1rK?w4N zhk!TY33w150KWZkL=wmmA=r^-zwzvRyYgpy*GoifIEi+MdPKzG5?cVA;Lr_A|aVlPg=}NUt{EZ68XSYcKWfW0PKRrJYqDQ_Kci}g`D?>!&&|^BH`!u45 zz*}_IJn@FXww4%I)yN@6FKJ8#@HL_ev*r}*w`I=#xWw(CK1SVzY?o@kt*Z^I;yg^% zxL?BaG%3o#;45owv@dlwIq&lBmF`RbR8)Q$l#^l@{Rqo6zuP5eZNbRGxc(E8Z+-`(9kob}!5!NH*K z-rl=2n>l>z#?HOtle4$)rtfDTKH-L73?GxSYX%$mj9@{K3qQ|Nk-b5_;WV`ttpZj7 ztH2rs%#y(`uc@(JRspNP|EYjnA6&RZ&tR=lEgfjo5dhdmS{Y*b( + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..99ec899 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..8afa588 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..aa19aaa --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +matrix: + include: + - language: node_js + node_js: node + before_install: + - cd server + install: + - nvm install node + - node -v + - npm install \ No newline at end of file diff --git a/.vscode/.ropeproject/config.py b/.vscode/.ropeproject/config.py new file mode 100644 index 0000000..dee2d1a --- /dev/null +++ b/.vscode/.ropeproject/config.py @@ -0,0 +1,114 @@ +# The default ``config.py`` +# flake8: noqa + + +def set_prefs(prefs): + """This function is called before opening the project""" + + # Specify which files and folders to ignore in the project. + # Changes to ignored resources are not added to the history and + # VCSs. Also they are not returned in `Project.get_files()`. + # Note that ``?`` and ``*`` match all characters but slashes. + # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc' + # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc' + # '.svn': matches 'pkg/.svn' and all of its children + # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o' + # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o' + prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', + '.hg', '.svn', '_svn', '.git', '.tox'] + + # Specifies which files should be considered python files. It is + # useful when you have scripts inside your project. Only files + # ending with ``.py`` are considered to be python files by + # default. + # prefs['python_files'] = ['*.py'] + + # Custom source folders: By default rope searches the project + # for finding source folders (folders that should be searched + # for finding modules). You can add paths to that list. Note + # that rope guesses project source folders correctly most of the + # time; use this if you have any problems. + # The folders should be relative to project root and use '/' for + # separating folders regardless of the platform rope is running on. + # 'src/my_source_folder' for instance. + # prefs.add('source_folders', 'src') + + # You can extend python path for looking up modules + # prefs.add('python_path', '~/python/') + + # Should rope save object information or not. + prefs['save_objectdb'] = True + prefs['compress_objectdb'] = False + + # If `True`, rope analyzes each module when it is being saved. + prefs['automatic_soa'] = True + # The depth of calls to follow in static object analysis + prefs['soa_followed_calls'] = 0 + + # If `False` when running modules or unit tests "dynamic object + # analysis" is turned off. This makes them much faster. + prefs['perform_doa'] = True + + # Rope can check the validity of its object DB when running. + prefs['validate_objectdb'] = True + + # How many undos to hold? + prefs['max_history_items'] = 32 + + # Shows whether to save history across sessions. + prefs['save_history'] = True + prefs['compress_history'] = False + + # Set the number spaces used for indenting. According to + # :PEP:`8`, it is best to use 4 spaces. Since most of rope's + # unit-tests use 4 spaces it is more reliable, too. + prefs['indent_size'] = 4 + + # Builtin and c-extension modules that are allowed to be imported + # and inspected by rope. + prefs['extension_modules'] = [] + + # Add all standard c-extensions to extension_modules list. + prefs['import_dynload_stdmods'] = True + + # If `True` modules with syntax errors are considered to be empty. + # The default value is `False`; When `False` syntax errors raise + # `rope.base.exceptions.ModuleSyntaxError` exception. + prefs['ignore_syntax_errors'] = False + + # If `True`, rope ignores unresolvable imports. Otherwise, they + # appear in the importing namespace. + prefs['ignore_bad_imports'] = False + + # If `True`, rope will insert new module imports as + # `from import ` by default. + prefs['prefer_module_from_imports'] = False + + # If `True`, rope will transform a comma list of imports into + # multiple separate import statements when organizing + # imports. + prefs['split_imports'] = False + + # If `True`, rope will remove all top-level import statements and + # reinsert them at the top of the module when making changes. + prefs['pull_imports_to_top'] = True + + # If `True`, rope will sort imports alphabetically by module name instead + # of alphabetically by import statement, with from imports after normal + # imports. + prefs['sort_imports_alphabetically'] = False + + # Location of implementation of + # rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general + # case, you don't have to change this value, unless you're an rope expert. + # Change this value to inject you own implementations of interfaces + # listed in module rope.base.oi.type_hinting.providers.interfaces + # For example, you can add you own providers for Django Models, or disable + # the search type-hinting in a class hierarchy, etc. + prefs['type_hinting_factory'] = ( + 'rope.base.oi.type_hinting.factory.default_type_hinting_factory') + + +def project_opened(project): + """This function is called after opening the project""" + # Do whatever you like here! diff --git a/README.md b/README.md index 53c996f..5b6c8ca 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ +| Branch | Build Status | +|-|-| +| Master | [![Build Status](https://travis-ci.org/Assis10t/assis10t.svg?branch=master)](https://travis-ci.org/Assis10t/assis10t) | +| Beta | [![Build Status](https://travis-ci.org/Assis10t/assis10t.svg?branch=beta)](https://travis-ci.org/Assis10t/assis10t) | + # assis10t Main repository for SDP Group 10 diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..fd45b12 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,11 @@ +*.iml +.gradle +/local.properties +/.idea/caches/build_file_checksums.ser +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/android/.idea/codeStyles/Project.xml b/android/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..34dc27c --- /dev/null +++ b/android/.idea/codeStyles/Project.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/.idea/codeStyles/codeStyleConfig.xml b/android/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/android/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/android/.idea/gradle.xml b/android/.idea/gradle.xml new file mode 100644 index 0000000..7ac24c7 --- /dev/null +++ b/android/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/android/.idea/misc.xml b/android/.idea/misc.xml new file mode 100644 index 0000000..51fa3e5 --- /dev/null +++ b/android/.idea/misc.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/android/.idea/runConfigurations.xml b/android/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/android/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/android/.idea/vcs.xml b/android/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/android/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/android/app/.gitignore b/android/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/android/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..b3b2e06 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,41 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "io.github.assis10t.bobandroid" + minSdkVersion 23 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support:design:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.android.support:support-v4:28.0.0' + implementation 'com.jakewharton.timber:timber:4.7.1' + testImplementation "com.nhaarman:mockito-kotlin:1.1.0" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'org.jmdns:jmdns:3.5.1' + implementation 'com.squareup.okhttp3:okhttp:3.12.0' + implementation 'com.google.code.gson:gson:2.8.5' + implementation 'org.jetbrains.anko:anko-common:0.9' +} diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/android/app/src/androidTest/java/io/github/assis10t/bobandroid/ExampleInstrumentedTest.kt b/android/app/src/androidTest/java/io/github/assis10t/bobandroid/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..56f23d6 --- /dev/null +++ b/android/app/src/androidTest/java/io/github/assis10t/bobandroid/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package io.github.assis10t.bobandroid + +import android.support.test.InstrumentationRegistry +import android.support.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getTargetContext() + assertEquals("io.github.assis10t.bobandroid", appContext.packageName) + } +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..0d5b330 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/Application.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/Application.kt new file mode 100644 index 0000000..21494dd --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/Application.kt @@ -0,0 +1,19 @@ +package io.github.assis10t.bobandroid + +import android.app.Application +import timber.log.Timber + +class Application: Application() { + + override fun onCreate() { + super.onCreate() + ServerConnection.initialize() + + //From: https://github.com/oktay-sen/Coinz + Timber.plant(object : Timber.DebugTree() { + override fun createStackElementTag(element: StackTraceElement): String? { + return super.createStackElementTag(element) + ':' + element.lineNumber + } + }) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/LoginActivity.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/LoginActivity.kt new file mode 100644 index 0000000..2e19fd1 --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/LoginActivity.kt @@ -0,0 +1,61 @@ +package io.github.assis10t.bobandroid + +import android.content.Intent +import android.support.v7.app.AppCompatActivity +import android.os.Bundle +import android.view.MenuItem +import kotlinx.android.synthetic.main.activity_login.* +import org.jetbrains.anko.toast + +class LoginActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_login) + + supportActionBar?.setDisplayShowHomeEnabled(true) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.setHomeButtonEnabled(true) + + login_button.setOnClickListener { + ServerConnection().login( + username.text.toString(), + md5(password.text.toString()) + ) { success, loggedIn -> + if (!success) { + toast("An error occured while logging in.") + } else if (!loggedIn) { + toast("Wrong username or password.") + } else { + val intent = Intent(this, MainActivity::class.java) + intent.putExtra("loggedIn", true) + startActivity(intent) + } + } + } + + register_button.setOnClickListener { + ServerConnection().register( + username.text.toString(), + md5(password.text.toString()) + ) { success -> + if (!success) { + toast("An error occured while registering.") + } else { + val intent = Intent(this, MainActivity::class.java) + intent.putExtra("loggedIn", true) + startActivity(intent) + } + } + } + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + if (item?.itemId == android.R.id.home) { + onBackPressed() + return true + } else { + return super.onOptionsItemSelected(item) + } + } +} diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/MainActivity.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/MainActivity.kt new file mode 100644 index 0000000..7bdea63 --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/MainActivity.kt @@ -0,0 +1,161 @@ +package io.github.assis10t.bobandroid + +import android.content.Intent +import android.support.v7.app.AppCompatActivity +import android.os.Bundle +import android.support.v7.widget.CardView +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.view.* +import android.widget.TextView +import io.github.assis10t.bobandroid.pojo.Item +import io.github.assis10t.bobandroid.pojo.Order +import kotlinx.android.synthetic.main.activity_main.* +import timber.log.Timber +import android.R.string.cancel +import android.content.DialogInterface +import android.support.v7.app.AlertDialog +import android.text.InputType +import android.widget.EditText + + + +class MainActivity : AppCompatActivity() { + + var loggedIn = false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + loggedIn = intent.getBooleanExtra("loggedIn", false) + + container.isRefreshing = true + container.setOnRefreshListener { refreshItems() } + ServerConnection().connect { + container.isRefreshing = false + } + item_list.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) + item_list.adapter = ItemAdapter { selected -> + if (selected.isEmpty()) + make_order.hide() + else + make_order.show() + } + + make_order.hide() + make_order.setOnClickListener { + container.isRefreshing = true + make_order.hide() + val adapter = item_list.adapter as ItemAdapter + ServerConnection().makeOrder(Order(null, adapter.selectedItems)) { success -> + if (!success) + Timber.e("Could not make order.") + else { + Timber.d("Order made.") + refreshItems() + } + } + } + } + + override fun onResume() { + super.onResume() + + refreshItems() + } + + fun refreshItems() { + container.isRefreshing = true + ServerConnection().getItems { success, items -> + container.isRefreshing = false + if (!success) { + Timber.e("getItems failed.") + return@getItems + } + Timber.d("GetItems success. Items: ${items?.size}") + val adapter = item_list.adapter as ItemAdapter + adapter.updateItems(items!!) + } + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.menu_toolbar, menu) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + // Handle item selection + return when (item.itemId) { + R.id.login -> { + startActivity(Intent(this, LoginActivity::class.java)) + true + } + R.id.zeroconf_bypass -> { + val builder = AlertDialog.Builder(this) + builder.setTitle("What's the address of the server?") + val input = EditText(this) + input.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI or InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE + input.text.insert(0, "192.168.") + builder.setView(input) + builder.setPositiveButton("Set") { dialog, which -> + ServerConnection.zeroconfBypass(input.text.toString()) + } + builder.setNegativeButton("Cancel") { dialog, which -> + dialog.cancel() + } + builder.show() + true + } + else -> super.onOptionsItemSelected(item) + } + } + + class ItemAdapter(var onSelectionChanged: (selected: List) -> Unit): RecyclerView.Adapter() { + var itemList: List = listOf() + val selectedItems: MutableList = mutableListOf() + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.fragment_shop_item, parent, false) + return ViewHolder(view) + } + + override fun getItemCount(): Int = itemList.size + + override fun onBindViewHolder(vh: ViewHolder, pos: Int) { + val item = itemList[pos] + val context = vh.container.context + vh.title.text = item.name + vh.container.setCardBackgroundColor( + if (selectedItems.contains(item)) + vh.container.context.getColor(R.color.selectHighlight) + else + vh.container.context.getColor(R.color.white) + ) + vh.container.cardElevation = + if (selectedItems.contains(item)) + dp(context, 4f) + else + dp(context, 1f) + vh.container.setOnClickListener { + if (selectedItems.contains(item)) + selectedItems.remove(item) + else + selectedItems.add(item) + onSelectionChanged(itemList) + notifyItemChanged(pos) + } + } + + fun updateItems(items: List) { + this.itemList = items + this.selectedItems.clear() + notifyDataSetChanged() + } + + class ViewHolder(view: View): RecyclerView.ViewHolder(view) { + val title: TextView = view.findViewById(R.id.title) + val quantity: TextView = view.findViewById(R.id.quantity) + val container: CardView = view.findViewById(R.id.container) + } + } +} diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/ServerConnection.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/ServerConnection.kt new file mode 100644 index 0000000..1118e6b --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/ServerConnection.kt @@ -0,0 +1,186 @@ +package io.github.assis10t.bobandroid + +import com.google.gson.Gson +import io.github.assis10t.bobandroid.pojo.* +import okhttp3.MediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody +import org.jetbrains.anko.doAsync +import org.jetbrains.anko.uiThread +import timber.log.Timber +import java.io.IOException +import javax.jmdns.JmDNS +import javax.jmdns.ServiceEvent +import javax.jmdns.ServiceListener + +class ServerConnection { + companion object { + val SERVER_NAME = "assis10t" + var serverAddress: String? = null + val httpClient: OkHttpClient = OkHttpClient() + + val onConnectedListeners: MutableList<(serverAddress: String) -> Unit> = mutableListOf() + + fun initialize() { + doAsync { + Timber.d("Discovery started") + val mJmDNS = JmDNS.create() + mJmDNS.addServiceListener("_http._tcp.local.", object : ServiceListener { + + override fun serviceResolved(event: ServiceEvent?) { + val info = mJmDNS.getServiceInfo(event!!.type, event.name) + Timber.d("Service resolved: $info") + if (info.name.contains(SERVER_NAME)) { + uiThread { + serverAddress = "http://${info.inet4Addresses[0]!!.hostAddress}:${info.port}" + onConnectedListeners.forEach { it(serverAddress!!) } + onConnectedListeners.clear() + } + } + } + + override fun serviceRemoved(event: ServiceEvent?) { + Timber.d("Service removed") + } + + override fun serviceAdded(event: ServiceEvent?) { + val info = mJmDNS.getServiceInfo(event!!.type, event.name) + Timber.d("Service added: $info") + } + }) + } + ServerConnection().connect { ip -> + Timber.d("Server found at $ip") + } + } + + fun zeroconfBypass(address: String) { + Timber.d("Bypassed zeroconf: $address") + serverAddress = "http://$address:9000" + onConnectedListeners.forEach { it(serverAddress!!) } + onConnectedListeners.clear() + } + } + + fun connect(onConnected: (String) -> Unit) { + if (serverAddress != null) + onConnected(serverAddress!!) + else + onConnectedListeners.add(onConnected) + } + + val getRequestFactory = { http: OkHttpClient -> + { url: String, onGetComplete: (success: Boolean, response: String?) -> Unit -> + doAsync { + Timber.d("Get request to $url") + try { + val request = Request.Builder().url(url).build() + val response = http.newCall(request).execute() + Timber.d("Response received.") + if (!response.isSuccessful) { + Timber.e("Get Request failed: (${response.code()}) ${response.body().toString()}") + uiThread { onGetComplete(false, null) } + } else { + uiThread { onGetComplete(true, response.body()?.string()) } + } + } catch (e: IOException) { + Timber.e(e, "Get Request failed") + uiThread { onGetComplete(false, null) } + } + } + } + } + + val postRequestFactory = { http: OkHttpClient, gson: Gson -> + { url: String, body: Any, onPostComplete: (success: Boolean, response: String?) -> Unit -> + doAsync { + Timber.d("Post request to $url") + try { + val JSON = MediaType.get("application/json; charset=utf-8") + val requestBody = RequestBody.create(JSON, gson.toJson(body)) + val request = Request.Builder().url(url).post(requestBody).build() + val response = http.newCall(request).execute() + Timber.d("Response received.") + if (!response.isSuccessful) { + Timber.e("Post Request failed: (${response.code()}) ${response.body().toString()}") + uiThread { onPostComplete(false, null) } + } else { + uiThread { onPostComplete(true, response.body()?.string()) } + } + } catch (e: IOException) { + Timber.e(e, "Post Request failed") + uiThread { onPostComplete(false, null) } + } + } + } + } + + val getItemsFactory = { http: OkHttpClient, gson: Gson -> + { onGetItems: (success: Boolean, items: List?) -> Unit -> + connect { server -> + getRequestFactory(http)("$server/items") { success, str -> + Timber.d("Result: $success, response: $str") + if (!success) { + onGetItems(success, null) + } else { + val response = gson.fromJson(str!!, GetItemsResponse::class.java) + onGetItems(response.success, response.items) + } + } + } + } + } + val getItems = getItemsFactory(httpClient, Gson()) + + val makeOrderFactory = { http: OkHttpClient, gson: Gson -> + { order: Order, onOrderComplete: ((success: Boolean) -> Unit)? -> + connect { server -> + postRequestFactory(http, gson)("$server/order", order) { success, str -> + Timber.d("Result: $success, response: $str") + if (!success) { + onOrderComplete?.invoke(success) + } else { + val response = gson.fromJson(str!!, GenericResponse::class.java) + onOrderComplete?.invoke(response.success) + } + } + } + } + } + val makeOrder = makeOrderFactory(httpClient, Gson()) + + val loginFactory = { http: OkHttpClient, gson: Gson -> + { username: String, password: String, onLoginComplete: ((success: Boolean, loggedIn: Boolean) -> Unit)? -> + connect { server -> + postRequestFactory(http, gson)("$server/login", LoginRequest(username, password)) { success, str -> + Timber.d("Result: $success, response: $str") + if (!success) { + onLoginComplete?.invoke(success, false) + } else { + val response = gson.fromJson(str!!, LoginResponse::class.java) + onLoginComplete?.invoke(response.success, response.loggedIn) + } + } + } + } + } + val login = loginFactory(httpClient, Gson()) + + val registerFactory = { http: OkHttpClient, gson: Gson -> + { username: String, password: String, onRegisterComplete: ((success: Boolean) -> Unit)? -> + connect { server -> + postRequestFactory(http, gson)("$server/register", RegisterRequest(username, password)) { success, str -> + Timber.d("Result: $success, response: $str") + if (!success) { + onRegisterComplete?.invoke(success) + } else { + val response = gson.fromJson(str!!, GenericResponse::class.java) + onRegisterComplete?.invoke(response.success) + } + } + } + } + } + val register = registerFactory(httpClient, Gson()) +} \ No newline at end of file diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/GenericResponse.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/GenericResponse.kt new file mode 100644 index 0000000..4869137 --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/GenericResponse.kt @@ -0,0 +1,3 @@ +package io.github.assis10t.bobandroid.pojo + +class GenericResponse(val success: Boolean = false) \ No newline at end of file diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/GetItemsResponse.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/GetItemsResponse.kt new file mode 100644 index 0000000..0f016e9 --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/GetItemsResponse.kt @@ -0,0 +1,3 @@ +package io.github.assis10t.bobandroid.pojo + +class GetItemsResponse(val success: Boolean = false, val items:List = listOf()) \ No newline at end of file diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/Item.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/Item.kt new file mode 100644 index 0000000..ac2644b --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/Item.kt @@ -0,0 +1,6 @@ +package io.github.assis10t.bobandroid.pojo + +class Item ( + val _id:String? = null, + val name:String? = null +) \ No newline at end of file diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/LoginRequest.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/LoginRequest.kt new file mode 100644 index 0000000..bc0e788 --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/LoginRequest.kt @@ -0,0 +1,6 @@ +package io.github.assis10t.bobandroid.pojo + +class LoginRequest ( + val username: String, + val password: String +) \ No newline at end of file diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/LoginResponse.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/LoginResponse.kt new file mode 100644 index 0000000..041e16f --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/LoginResponse.kt @@ -0,0 +1,6 @@ +package io.github.assis10t.bobandroid.pojo + +class LoginResponse ( + val success: Boolean = false, + val loggedIn: Boolean = false +) \ No newline at end of file diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/Order.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/Order.kt new file mode 100644 index 0000000..74d3da4 --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/Order.kt @@ -0,0 +1,6 @@ +package io.github.assis10t.bobandroid.pojo + +class Order( + val _id: String? = null, + val items: List = listOf() +) \ No newline at end of file diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/RegisterRequest.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/RegisterRequest.kt new file mode 100644 index 0000000..fd68537 --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/pojo/RegisterRequest.kt @@ -0,0 +1,6 @@ +package io.github.assis10t.bobandroid.pojo + +class RegisterRequest ( + val username: String, + val password: String +) \ No newline at end of file diff --git a/android/app/src/main/java/io/github/assis10t/bobandroid/utils.kt b/android/app/src/main/java/io/github/assis10t/bobandroid/utils.kt new file mode 100644 index 0000000..56c1bfd --- /dev/null +++ b/android/app/src/main/java/io/github/assis10t/bobandroid/utils.kt @@ -0,0 +1,36 @@ +package io.github.assis10t.bobandroid + +import android.content.Context +import android.util.TypedValue +import android.provider.SyncStateContract.Helpers.update +import java.security.NoSuchAlgorithmException + + +fun dp(context: Context, dp: Float) = + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.resources.displayMetrics) + +//From: http://www.kospol.gr/204/create-md5-hashes-in-android/ +fun md5(s: String): String { + try { + // Create MD5 Hash + val digest = java.security.MessageDigest + .getInstance("MD5") + digest.update(s.toByteArray()) + val messageDigest = digest.digest() + + // Create Hex String + val hexString = StringBuffer() + for (i in messageDigest.indices) { + var h = Integer.toHexString(0xFF and messageDigest[i].toInt()) + while (h.length < 2) + h = "0$h" + hexString.append(h) + } + return hexString.toString() + + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } + + return "" +} \ No newline at end of file diff --git a/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..6348baa --- /dev/null +++ b/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/android/app/src/main/res/drawable/ic_launcher_background.xml b/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..a0ad202 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/drawable/ic_send_black_24dp.xml b/android/app/src/main/res/drawable/ic_send_black_24dp.xml new file mode 100644 index 0000000..e145ca8 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_send_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/app/src/main/res/layout/activity_login.xml b/android/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..6a9c4ce --- /dev/null +++ b/android/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,50 @@ + + + + + + + + +

Stop BOB!

+ +

Login

+ + +
+ + +
+ + + \ No newline at end of file diff --git a/server/public/md5.min.js b/server/public/md5.min.js new file mode 100644 index 0000000..e533235 --- /dev/null +++ b/server/public/md5.min.js @@ -0,0 +1,510 @@ +!(function(n) { + 'use strict' + function t(n, t) { + var r = (65535 & n) + (65535 & t) + return (((n >> 16) + (t >> 16) + (r >> 16)) << 16) | (65535 & r) + } + function r(n, t) { + return (n << t) | (n >>> (32 - t)) + } + function e(n, e, o, u, c, f) { + return t(r(t(t(e, n), t(u, f)), c), o) + } + function o(n, t, r, o, u, c, f) { + return e((t & r) | (~t & o), n, t, u, c, f) + } + function u(n, t, r, o, u, c, f) { + return e((t & o) | (r & ~o), n, t, u, c, f) + } + function c(n, t, r, o, u, c, f) { + return e(t ^ r ^ o, n, t, u, c, f) + } + function f(n, t, r, o, u, c, f) { + return e(r ^ (t | ~o), n, t, u, c, f) + } + function i(n, r) { + ;(n[r >> 5] |= 128 << r % 32), (n[14 + (((r + 64) >>> 9) << 4)] = r) + var e, + i, + a, + d, + h, + l = 1732584193, + g = -271733879, + v = -1732584194, + m = 271733878 + for (e = 0; e < n.length; e += 16) + (i = l), + (a = g), + (d = v), + (h = m), + (g = f( + (g = f( + (g = f( + (g = f( + (g = c( + (g = c( + (g = c( + (g = c( + (g = u( + (g = u( + (g = u( + (g = u( + (g = o( + (g = o( + (g = o( + (g = o( + g, + (v = o( + v, + (m = o( + m, + (l = o( + l, + g, + v, + m, + n[e], + 7, + -680876936 + )), + g, + v, + n[e + 1], + 12, + -389564586 + )), + l, + g, + n[e + 2], + 17, + 606105819 + )), + m, + l, + n[e + 3], + 22, + -1044525330 + )), + (v = o( + v, + (m = o( + m, + (l = o( + l, + g, + v, + m, + n[e + 4], + 7, + -176418897 + )), + g, + v, + n[e + 5], + 12, + 1200080426 + )), + l, + g, + n[e + 6], + 17, + -1473231341 + )), + m, + l, + n[e + 7], + 22, + -45705983 + )), + (v = o( + v, + (m = o( + m, + (l = o( + l, + g, + v, + m, + n[e + 8], + 7, + 1770035416 + )), + g, + v, + n[e + 9], + 12, + -1958414417 + )), + l, + g, + n[e + 10], + 17, + -42063 + )), + m, + l, + n[e + 11], + 22, + -1990404162 + )), + (v = o( + v, + (m = o( + m, + (l = o( + l, + g, + v, + m, + n[e + 12], + 7, + 1804603682 + )), + g, + v, + n[e + 13], + 12, + -40341101 + )), + l, + g, + n[e + 14], + 17, + -1502002290 + )), + m, + l, + n[e + 15], + 22, + 1236535329 + )), + (v = u( + v, + (m = u( + m, + (l = u(l, g, v, m, n[e + 1], 5, -165796510)), + g, + v, + n[e + 6], + 9, + -1069501632 + )), + l, + g, + n[e + 11], + 14, + 643717713 + )), + m, + l, + n[e], + 20, + -373897302 + )), + (v = u( + v, + (m = u( + m, + (l = u(l, g, v, m, n[e + 5], 5, -701558691)), + g, + v, + n[e + 10], + 9, + 38016083 + )), + l, + g, + n[e + 15], + 14, + -660478335 + )), + m, + l, + n[e + 4], + 20, + -405537848 + )), + (v = u( + v, + (m = u( + m, + (l = u(l, g, v, m, n[e + 9], 5, 568446438)), + g, + v, + n[e + 14], + 9, + -1019803690 + )), + l, + g, + n[e + 3], + 14, + -187363961 + )), + m, + l, + n[e + 8], + 20, + 1163531501 + )), + (v = u( + v, + (m = u( + m, + (l = u(l, g, v, m, n[e + 13], 5, -1444681467)), + g, + v, + n[e + 2], + 9, + -51403784 + )), + l, + g, + n[e + 7], + 14, + 1735328473 + )), + m, + l, + n[e + 12], + 20, + -1926607734 + )), + (v = c( + v, + (m = c( + m, + (l = c(l, g, v, m, n[e + 5], 4, -378558)), + g, + v, + n[e + 8], + 11, + -2022574463 + )), + l, + g, + n[e + 11], + 16, + 1839030562 + )), + m, + l, + n[e + 14], + 23, + -35309556 + )), + (v = c( + v, + (m = c( + m, + (l = c(l, g, v, m, n[e + 1], 4, -1530992060)), + g, + v, + n[e + 4], + 11, + 1272893353 + )), + l, + g, + n[e + 7], + 16, + -155497632 + )), + m, + l, + n[e + 10], + 23, + -1094730640 + )), + (v = c( + v, + (m = c( + m, + (l = c(l, g, v, m, n[e + 13], 4, 681279174)), + g, + v, + n[e], + 11, + -358537222 + )), + l, + g, + n[e + 3], + 16, + -722521979 + )), + m, + l, + n[e + 6], + 23, + 76029189 + )), + (v = c( + v, + (m = c( + m, + (l = c(l, g, v, m, n[e + 9], 4, -640364487)), + g, + v, + n[e + 12], + 11, + -421815835 + )), + l, + g, + n[e + 15], + 16, + 530742520 + )), + m, + l, + n[e + 2], + 23, + -995338651 + )), + (v = f( + v, + (m = f( + m, + (l = f(l, g, v, m, n[e], 6, -198630844)), + g, + v, + n[e + 7], + 10, + 1126891415 + )), + l, + g, + n[e + 14], + 15, + -1416354905 + )), + m, + l, + n[e + 5], + 21, + -57434055 + )), + (v = f( + v, + (m = f( + m, + (l = f(l, g, v, m, n[e + 12], 6, 1700485571)), + g, + v, + n[e + 3], + 10, + -1894986606 + )), + l, + g, + n[e + 10], + 15, + -1051523 + )), + m, + l, + n[e + 1], + 21, + -2054922799 + )), + (v = f( + v, + (m = f(m, (l = f(l, g, v, m, n[e + 8], 6, 1873313359)), g, v, n[e + 15], 10, -30611744)), + l, + g, + n[e + 6], + 15, + -1560198380 + )), + m, + l, + n[e + 13], + 21, + 1309151649 + )), + (v = f( + v, + (m = f(m, (l = f(l, g, v, m, n[e + 4], 6, -145523070)), g, v, n[e + 11], 10, -1120210379)), + l, + g, + n[e + 2], + 15, + 718787259 + )), + m, + l, + n[e + 9], + 21, + -343485551 + )), + (l = t(l, i)), + (g = t(g, a)), + (v = t(v, d)), + (m = t(m, h)) + return [l, g, v, m] + } + function a(n) { + var t, + r = '', + e = 32 * n.length + for (t = 0; t < e; t += 8) r += String.fromCharCode((n[t >> 5] >>> t % 32) & 255) + return r + } + function d(n) { + var t, + r = [] + for (r[(n.length >> 2) - 1] = void 0, t = 0; t < r.length; t += 1) r[t] = 0 + var e = 8 * n.length + for (t = 0; t < e; t += 8) r[t >> 5] |= (255 & n.charCodeAt(t / 8)) << t % 32 + return r + } + function h(n) { + return a(i(d(n), 8 * n.length)) + } + function l(n, t) { + var r, + e, + o = d(n), + u = [], + c = [] + for (u[15] = c[15] = void 0, o.length > 16 && (o = i(o, 8 * n.length)), r = 0; r < 16; r += 1) + (u[r] = 909522486 ^ o[r]), (c[r] = 1549556828 ^ o[r]) + return (e = i(u.concat(d(t)), 512 + 8 * t.length)), a(i(c.concat(e), 640)) + } + function g(n) { + var t, + r, + e = '' + for (r = 0; r < n.length; r += 1) + (t = n.charCodeAt(r)), (e += '0123456789abcdef'.charAt((t >>> 4) & 15) + '0123456789abcdef'.charAt(15 & t)) + return e + } + function v(n) { + return unescape(encodeURIComponent(n)) + } + function m(n) { + return h(v(n)) + } + function p(n) { + return g(m(n)) + } + function s(n, t) { + return l(v(n), v(t)) + } + function C(n, t) { + return g(s(n, t)) + } + function A(n, t, r) { + return t ? (r ? s(t, n) : C(t, n)) : r ? m(n) : p(n) + } + 'function' == typeof define && define.amd + ? define(function() { + return A + }) + : 'object' == typeof module && module.exports + ? (module.exports = A) + : (n.md5 = A) +})(this) +//# sourceMappingURL=md5.min.js.map diff --git a/server/utils.js b/server/utils.js new file mode 100644 index 0000000..4a76364 --- /dev/null +++ b/server/utils.js @@ -0,0 +1,34 @@ +const os = require('os') + +let ips = null + +module.exports.getIp = () => { + if (ips && ips.length > 0) return ips[0] + + ips = [] + const ifaces = os.networkInterfaces() + console.log('===== IP ADDRESSES =====') + Object.keys(ifaces).forEach(function(ifname) { + let alias = 0 + + ifaces[ifname].forEach(function(iface) { + if ('IPv4' !== iface.family || iface.internal !== false) { + // skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses + return + } + + ips.push(iface.address) + + if (alias >= 1) { + // this single interface has multiple ipv4 addresses + console.log(ifname + ':' + alias, iface.address) + } else { + // this interface has only one ipv4 adress + console.log(ifname, iface.address) + } + ++alias + }) + }) + console.log('=== END IP ADDRESSES ===') + return ips[0] +}