├── .env.example ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── app ├── Core │ ├── Doctrine │ │ ├── AnnotationsServiceProvider.php │ │ └── CacheBridge.php │ ├── Exceptions │ │ └── Handler.php │ ├── Lazy │ │ └── Fetch.php │ ├── Mappers │ │ └── Message │ │ │ ├── MessageMapper.php │ │ │ ├── RelationMapper.php │ │ │ └── UrlMapper.php │ ├── Observers │ │ └── IdObserver.php │ ├── Providers │ │ ├── AppServiceProvider.php │ │ ├── AuthServiceProvider.php │ │ ├── EventServiceProvider.php │ │ ├── GitterClientServiceProvider.php │ │ ├── OrmServiceProvider.php │ │ └── RouteServiceProvider.php │ └── Support │ │ └── helpers.php ├── Domains │ ├── Achieve.php │ ├── Analyser │ │ ├── Analyser.php │ │ ├── MessageRelations.php │ │ └── UrlFinder.php │ ├── Bot │ │ ├── AchieveSubscriber.php │ │ ├── Achievements │ │ │ ├── DocsAchieve.php │ │ │ ├── GrumblerAchieve.php │ │ │ ├── Karma1000Achieve.php │ │ │ ├── Karma100Achieve.php │ │ │ ├── Karma10Achieve.php │ │ │ ├── Karma500Achieve.php │ │ │ ├── Karma50Achieve.php │ │ │ ├── ReaderAchieve.php │ │ │ ├── Thanks100Achieve.php │ │ │ ├── Thanks10Karma0Achieve.php │ │ │ ├── Thanks20Achieve.php │ │ │ └── Thanks50Achieve.php │ │ ├── ClientInterface.php │ │ ├── Middlewares │ │ │ ├── GoogleSearchMiddleware.php │ │ │ ├── InlineDataMiddleware.php │ │ │ ├── KarmaCounterMiddleware.php │ │ │ ├── KarmaRenderMiddleware.php │ │ │ ├── LaravelDocumentationSearcherMiddleware.php │ │ │ ├── LongMessageMiddleware.php │ │ │ ├── MarkdownAdviserMiddleware.php │ │ │ ├── NewGoogleSearchMiddleware.php │ │ │ ├── PersonalAnswersMiddleware.php │ │ │ └── SqlBuilderMiddleware.php │ │ └── TextParserInterface.php │ ├── BotManager.php │ ├── Karma.php │ ├── Message.php │ ├── Message │ │ ├── FormatterInterface.php │ │ ├── Message.php │ │ ├── Relation.php │ │ └── Url.php │ ├── Middleware │ │ ├── MiddlewareGroupableInterface.php │ │ ├── MiddlewareInterface.php │ │ └── Storage.php │ ├── Room │ │ ├── AbstractRoom.php │ │ └── RoomInterface.php │ ├── RoomManager.php │ ├── Subscriber │ │ ├── Storage.php │ │ └── SubscriberInterface.php │ ├── User.php │ └── User │ │ ├── Mention.php │ │ └── User.php └── Interfaces │ ├── Console │ ├── Commands │ │ ├── GetGitterRoomId.php │ │ ├── StartGitterBot.php │ │ └── StartGitterPool.php │ └── Kernel.php │ ├── Gitter │ ├── Achieve │ │ ├── AbstractAchieve.php │ │ └── AchieveInterface.php │ ├── Ai.php │ ├── Ai │ │ └── UserChannel.php │ ├── Client.php │ ├── Console │ │ └── CircleProgress.php │ ├── Http │ │ ├── Request.php │ │ ├── Stream.php │ │ └── UrlStorage.php │ ├── Karma │ │ ├── Status.php │ │ └── Validator.php │ ├── MessageMapper.php │ ├── StandartGitterRoom.php │ ├── Support │ │ ├── AttributeMapper.php │ │ ├── PriorityList.php │ │ └── StreamBuffer.php │ ├── TextParser.php │ └── UserMapper.php │ ├── Google │ └── GoogleSearch.php │ ├── Http │ ├── Controllers │ │ ├── Api │ │ │ ├── AchievementsController.php │ │ │ └── UsersController.php │ │ ├── Controller.php │ │ └── HomeController.php │ ├── Kernel.php │ ├── Middleware │ │ ├── Authenticate.php │ │ ├── EncryptCookies.php │ │ ├── RedirectIfAuthenticated.php │ │ └── VerifyCsrfToken.php │ ├── Requests │ │ └── Request.php │ └── routes.php │ └── Slack │ ├── Client.php │ ├── MessageMapper.php │ ├── StandartSlackRoom.php │ ├── TextParser.php │ └── UserMapper.php ├── artisan ├── bootstrap ├── app.php ├── autoload.php └── cache │ └── .gitignore ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── compile.php ├── database.php ├── filesystems.php ├── gitter.php ├── google.php ├── mail.php ├── queue.php ├── services.php ├── session.php ├── slack.php └── view.php ├── database ├── .gitignore ├── factories │ └── ModelFactory.php ├── migrations │ ├── .gitkeep │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2015_10_09_201137_create_karma_table.php │ ├── 2015_10_11_055740_create_achievements_table.php │ ├── 2015_10_14_165107_remove_negative_karma.php │ ├── 2015_10_15_204513_remove_unused_achievement_fields.php │ └── 2016_04_09_034004_create_messages_table.php └── seeds │ ├── .gitkeep │ └── DatabaseSeeder.php ├── gulpfile.js ├── package.json ├── phpunit.xml ├── public ├── .htaccess ├── assets │ ├── app.css │ ├── app.css.gz │ ├── app.css.map │ ├── app.js │ ├── app.js.gz │ └── app.js.map ├── favicon.ico ├── favicon.png ├── fonts │ ├── fa │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ └── fira-4.1 │ │ ├── FiraSans-Bold.eot │ │ ├── FiraSans-Bold.ttf │ │ ├── FiraSans-Bold.woff │ │ ├── FiraSans-Bold.woff2 │ │ ├── FiraSans-BoldItalic.eot │ │ ├── FiraSans-BoldItalic.ttf │ │ ├── FiraSans-BoldItalic.woff │ │ ├── FiraSans-BoldItalic.woff2 │ │ ├── FiraSans-Book.eot │ │ ├── FiraSans-Book.ttf │ │ ├── FiraSans-Book.woff │ │ ├── FiraSans-Book.woff2 │ │ ├── FiraSans-BookItalic.eot │ │ ├── FiraSans-BookItalic.ttf │ │ ├── FiraSans-BookItalic.woff │ │ ├── FiraSans-BookItalic.woff2 │ │ ├── FiraSans-ExtraBold.eot │ │ ├── FiraSans-ExtraBold.ttf │ │ ├── FiraSans-ExtraBold.woff │ │ ├── FiraSans-ExtraBold.woff2 │ │ ├── FiraSans-ExtraBoldItalic.eot │ │ ├── FiraSans-ExtraBoldItalic.ttf │ │ ├── FiraSans-ExtraBoldItalic.woff │ │ ├── FiraSans-ExtraBoldItalic.woff2 │ │ ├── FiraSans-ExtraLight.eot │ │ ├── FiraSans-ExtraLight.ttf │ │ ├── FiraSans-ExtraLight.woff │ │ ├── FiraSans-ExtraLight.woff2 │ │ ├── FiraSans-ExtraLightItalic.eot │ │ ├── FiraSans-ExtraLightItalic.ttf │ │ ├── FiraSans-ExtraLightItalic.woff │ │ ├── FiraSans-ExtraLightItalic.woff2 │ │ ├── FiraSans-Heavy.eot │ │ ├── FiraSans-Heavy.ttf │ │ ├── FiraSans-Heavy.woff │ │ ├── FiraSans-Heavy.woff2 │ │ ├── FiraSans-HeavyItalic.eot │ │ ├── FiraSans-HeavyItalic.ttf │ │ ├── FiraSans-HeavyItalic.woff │ │ ├── FiraSans-HeavyItalic.woff2 │ │ ├── FiraSans-Italic.eot │ │ ├── FiraSans-Italic.ttf │ │ ├── FiraSans-Italic.woff │ │ ├── FiraSans-Italic.woff2 │ │ ├── FiraSans-Light.eot │ │ ├── FiraSans-Light.ttf │ │ ├── FiraSans-Light.woff │ │ ├── FiraSans-Light.woff2 │ │ ├── FiraSans-LightItalic.eot │ │ ├── FiraSans-LightItalic.ttf │ │ ├── FiraSans-LightItalic.woff │ │ ├── FiraSans-LightItalic.woff2 │ │ ├── FiraSans-Medium.eot │ │ ├── FiraSans-Medium.ttf │ │ ├── FiraSans-Medium.woff │ │ ├── FiraSans-Medium.woff2 │ │ ├── FiraSans-MediumItalic.eot │ │ ├── FiraSans-MediumItalic.ttf │ │ ├── FiraSans-MediumItalic.woff │ │ ├── FiraSans-MediumItalic.woff2 │ │ ├── FiraSans-Regular.eot │ │ ├── FiraSans-Regular.ttf │ │ ├── FiraSans-Regular.woff │ │ ├── FiraSans-Regular.woff2 │ │ ├── FiraSans-SemiBold.eot │ │ ├── FiraSans-SemiBold.ttf │ │ ├── FiraSans-SemiBold.woff │ │ ├── FiraSans-SemiBold.woff2 │ │ ├── FiraSans-SemiBoldItalic.eot │ │ ├── FiraSans-SemiBoldItalic.ttf │ │ ├── FiraSans-SemiBoldItalic.woff │ │ └── FiraSans-SemiBoldItalic.woff2 ├── img │ ├── achievements │ │ ├── docs.gif │ │ ├── grumbler.gif │ │ ├── karma-10.gif │ │ ├── karma-100.gif │ │ ├── karma-1000.gif │ │ ├── karma-50.gif │ │ ├── karma-500.gif │ │ ├── reader.gif │ │ ├── thanks-10-karma-0.gif │ │ ├── thanks-100.gif │ │ ├── thanks-20.gif │ │ └── thanks-50.gif │ ├── cloud-bar.png │ ├── events │ │ └── newyear.gif │ └── laravel-logo.png ├── index.php └── robots.txt ├── resources ├── achieve │ ├── achieve.psd │ ├── icon-achieve-10.psd │ └── vault.psd ├── javascripts │ ├── .gitkeep │ ├── Application.js │ ├── Controllers │ │ ├── AchievementsController.js │ │ ├── BaseController.js │ │ ├── Partials │ │ │ ├── HeaderController.js │ │ │ └── RequestNotifiesController.js │ │ ├── SearchController.js │ │ └── UserController.js │ ├── Lib │ │ ├── Collection.js │ │ ├── Config.js │ │ ├── Md5.js │ │ ├── Model.js │ │ ├── Request.js │ │ ├── Request │ │ │ └── RequestMessage.js │ │ └── Router.js │ ├── Models │ │ ├── Achieve.js │ │ ├── Karma.js │ │ ├── Thank.js │ │ └── User.js │ ├── Reflection │ │ └── Serialize.js │ └── Std │ │ └── Abstract.js ├── lang │ ├── en │ │ ├── auth.php │ │ ├── karma.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ ├── request.php │ │ └── validation.php │ └── ru │ │ ├── achieve.php │ │ ├── gitter.php │ │ ├── google.php │ │ ├── karma.php │ │ ├── long.php │ │ ├── markdown.php │ │ ├── pagination.php │ │ ├── personal.php │ │ ├── reminders.php │ │ ├── request.php │ │ ├── search.php │ │ ├── thanks.php │ │ └── validation.php ├── stylesheets │ ├── .gitkeep │ ├── layout.scss │ ├── layout │ │ ├── header.scss │ │ ├── profile.scss │ │ ├── search.scss │ │ └── users.scss │ ├── system │ │ └── sass_functions.scss │ ├── ui.scss │ ├── ui │ │ ├── fonts.scss │ │ ├── inputs.scss │ │ ├── labels.scss │ │ └── preloader.scss │ └── vendor │ │ ├── font-awesome.scss │ │ ├── font-awesome │ │ ├── animated.scss │ │ ├── bordered-pulled.scss │ │ ├── core.scss │ │ ├── fixed-width.scss │ │ ├── icons.scss │ │ ├── larger.scss │ │ ├── list.scss │ │ ├── mixins.scss │ │ ├── path.scss │ │ ├── rotated-flipped.scss │ │ ├── spinning.scss │ │ ├── stacked.scss │ │ └── variables.scss │ │ ├── normalize.scss │ │ └── utils.scss └── views │ ├── home.blade.php │ ├── layout │ └── master.blade.php │ ├── page │ ├── achievements.blade.php │ ├── search.blade.php │ ├── user.blade.php │ └── user │ │ ├── aside.blade.php │ │ └── profile.blade.php │ └── partials │ ├── header.blade.php │ └── notifies.blade.php ├── server.php ├── storage ├── app │ └── .gitignore ├── assets │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── views │ │ └── .gitignore ├── logs │ └── .gitignore ├── pids │ └── .gitignore └── sync │ └── .gitignore ├── tests ├── AbstractTestCase.php └── KarmaValidatorTest.php └── yarn.lock /.env.example: -------------------------------------------------------------------------------- 1 | APP_ENV=local 2 | APP_DEBUG=true 3 | APP_KEY=SomeRandomString 4 | 5 | GITTER_TOKEN=null 6 | 7 | DB_HOST=localhost 8 | DB_DATABASE=homestead 9 | DB_USERNAME=homestead 10 | DB_PASSWORD=secret 11 | 12 | CACHE_DRIVER=file 13 | SESSION_DRIVER=file 14 | QUEUE_DRIVER=sync 15 | 16 | MAIL_DRIVER=smtp 17 | MAIL_HOST=mailtrap.io 18 | MAIL_PORT=2525 19 | MAIL_USERNAME=null 20 | MAIL_PASSWORD=null 21 | MAIL_ENCRYPTION=null 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.less linguist-vendored 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /node_modules 3 | Homestead.yaml 4 | Homestead.json 5 | .env 6 | /.idea 7 | /storage/database.sqlite 8 | /_ide_helper.php 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Laravel Framework Russian Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /app/Core/Doctrine/AnnotationsServiceProvider.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 03.03.2016 15:00 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | 14 | namespace Core\Providers; 15 | 16 | use Core\Doctrine\CacheBridge; 17 | use Doctrine\Common\Annotations\AnnotationReader; 18 | use Doctrine\Common\Annotations\AnnotationRegistry; 19 | use Doctrine\Common\Annotations\CachedReader; 20 | use Doctrine\Common\Annotations\Reader; 21 | use Doctrine\Common\Cache\ArrayCache; 22 | use Illuminate\Contracts\Config\Repository; 23 | use Illuminate\Contracts\Foundation\Application; 24 | use Illuminate\Support\ServiceProvider; 25 | 26 | /** 27 | * Class AnnotationsServiceProvider 28 | * @package Core\Providers 29 | */ 30 | class AnnotationsServiceProvider extends ServiceProvider 31 | { 32 | /** 33 | * Register class 34 | * @throws \InvalidArgumentException 35 | */ 36 | public function register() 37 | { 38 | AnnotationRegistry::registerLoader(function ($class) { 39 | return class_exists($class); 40 | }); 41 | 42 | $this->app->singleton(Reader::class, function (Application $app) { 43 | $debug = $app->make(Repository::class)->get('app.debug', false); 44 | $cache = $app->make($debug ? ArrayCache::class : CacheBridge::class); 45 | 46 | return new CachedReader(new AnnotationReader(), $cache, $debug); 47 | }); 48 | 49 | $this->app->alias(AnnotationReader::class, Reader::class); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/Core/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | getMessage(), $e); 47 | } 48 | 49 | return parent::render($request, $e); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/Core/Lazy/Fetch.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 28.03.2016 14:02 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | 14 | namespace Core\Lazy; 15 | 16 | use Illuminate\Database\Eloquent\Model; 17 | use Illuminate\Database\Eloquent\Builder; 18 | 19 | /** 20 | * Class Fetch 21 | * @package Core\Lazy 22 | */ 23 | class Fetch implements \IteratorAggregate 24 | { 25 | const DEFAULT_CHUNK_SIZE = 1000; 26 | 27 | /** 28 | * @var int 29 | */ 30 | private $chunk = self::DEFAULT_CHUNK_SIZE; 31 | 32 | /** 33 | * @var Builder 34 | */ 35 | private $builder; 36 | 37 | /** 38 | * Fetch constructor. 39 | * @param Builder $builder 40 | * @param int $chunk 41 | */ 42 | public function __construct(Builder $builder, $chunk = self::DEFAULT_CHUNK_SIZE) 43 | { 44 | $this->builder = $builder; 45 | $this->chunk = $chunk; 46 | } 47 | 48 | /** 49 | * @return \Generator 50 | */ 51 | public function getIterator() 52 | { 53 | /** @var Builder|\Illuminate\Database\Query\Builder|Model $query */ 54 | $query = clone $this->builder; 55 | 56 | $skip = 0; 57 | $count = $query->count(); 58 | do { 59 | $items = $query->skip($skip)->take($this->chunk)->get(); 60 | foreach ($items as $item) { 61 | yield $item; 62 | } 63 | $skip += $this->chunk; 64 | } while ($skip < $count + $this->chunk); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Core/Mappers/Message/RelationMapper.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 28.03.2016 18:07 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | namespace Core\Mappers\Message; 13 | 14 | use Domains\Message\Message; 15 | use Illuminate\Database\Eloquent\Model; 16 | 17 | /** 18 | * Class Relation 19 | * @package Domains\Message 20 | * 21 | * @property-read Message $answer 22 | * @property-read Message $question 23 | */ 24 | class RelationMapper extends Model 25 | { 26 | /** 27 | * @var string 28 | */ 29 | protected $table = 'message_relations'; 30 | 31 | /** 32 | * @return \Illuminate\Database\Eloquent\Relations\HasOne 33 | */ 34 | public function answer() 35 | { 36 | return $this->hasOne(Message::class, 'id', 'answer_id'); 37 | } 38 | 39 | /** 40 | * @return \Illuminate\Database\Eloquent\Relations\HasOne 41 | */ 42 | public function question() 43 | { 44 | return $this->hasOne(Message::class, 'id', 'message_id'); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/Core/Mappers/Message/UrlMapper.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 09.04.2016 4:17 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Core\Mappers\Message; 12 | 13 | use Domains\Message\Message; 14 | use Illuminate\Database\Eloquent\Model; 15 | 16 | /** 17 | * Class UrlMapper 18 | * @package Core\Mappers\Message 19 | * 20 | * @property-read Message $message 21 | */ 22 | class UrlMapper extends Model 23 | { 24 | /** 25 | * @var bool 26 | */ 27 | public $timestamps = false; 28 | 29 | /** 30 | * @var string 31 | */ 32 | protected $table = 'urls'; 33 | 34 | /** 35 | * @var array 36 | */ 37 | protected $fillable = ['url']; 38 | 39 | /** 40 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 41 | */ 42 | public function message() 43 | { 44 | return $this->belongsTo(Message::class, 'message_id', 'id'); 45 | } 46 | } -------------------------------------------------------------------------------- /app/Core/Observers/IdObserver.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 28.03.2016 15:52 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | 14 | namespace Core\Observers; 15 | 16 | use Ramsey\Uuid\Uuid; 17 | use Illuminate\Database\Eloquent\Model; 18 | 19 | /** 20 | * Class IdObserver 21 | * @package Core\Observers 22 | */ 23 | class IdObserver 24 | { 25 | /** 26 | * @param Model $model 27 | */ 28 | public function saving(Model $model) 29 | { 30 | if (!$model->id) { 31 | $model->id = Uuid::uuid4()->toString(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Core/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 09.04.2016 3:51 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Core\Providers; 12 | 13 | use Core\Observers\IdObserver; 14 | use Domains\Message\Message; 15 | use Domains\Message\Relation; 16 | use Domains\Message\Url; 17 | use Domains\User\Mention; 18 | use Illuminate\Support\ServiceProvider; 19 | 20 | /** 21 | * Class OrmServiceProvider 22 | * @package Core\Providers 23 | */ 24 | class OrmServiceProvider extends ServiceProvider 25 | { 26 | /** 27 | * @return void 28 | */ 29 | public function register() 30 | { 31 | // Do nothing 32 | } 33 | 34 | /** 35 | * @return void 36 | */ 37 | public function boot() 38 | { 39 | Url::observe(IdObserver::class); 40 | Message::observe(IdObserver::class); 41 | Message::observe(IdObserver::class); 42 | Mention::observe(IdObserver::class); 43 | Relation::observe(IdObserver::class); 44 | } 45 | } -------------------------------------------------------------------------------- /app/Core/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | group(['namespace' => $this->namespace], function ($router) { 41 | require app_path('Interfaces/Http/routes.php'); 42 | }); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Core/Support/helpers.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 28.03.2016 23:55 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | 14 | namespace Domains\Analyser; 15 | 16 | /** 17 | * Interface Analyser 18 | * @package Domains\Analyser 19 | */ 20 | interface Analyser 21 | { 22 | /** 23 | * @return Analyser 24 | */ 25 | public function clear() : Analyser; 26 | 27 | /** 28 | * @param \Closure|null $progress 29 | * @return Analyser 30 | */ 31 | public function analyse(\Closure $progress = null) : Analyser; 32 | } 33 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/DocsAchieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class DocsAchieve 18 | */ 19 | class DocsAchieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'Красавчик'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Помог переводить документацию. Настоящий мужик!'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/docs.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | // Only manual addition 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/GrumblerAchieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class GrumblerAchieve 18 | */ 19 | class GrumblerAchieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'Почётный ворчун'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Заворчит вас до смерти'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/grumbler.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | // This special achievement 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/Karma1000Achieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class Karma1000Achieve 18 | */ 19 | class Karma1000Achieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'JhaoDa'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Больше кармы богу кармы!'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/karma-1000.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | Karma::created(function (Karma $karma) { 42 | $count = $karma->target->karma->count(); 43 | 44 | if ($count === 1000) { 45 | $this->create($karma->target, $karma->created_at); 46 | } 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/Karma100Achieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class Karma100Achieve 18 | */ 19 | class Karma100Achieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'Благодетель'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Набрать 100 кармы.'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/karma-100.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | Karma::created(function (Karma $karma) { 42 | $count = $karma->target->karma->count(); 43 | 44 | if ($count === 100) { 45 | $this->create($karma->target, $karma->created_at); 46 | } 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/Karma10Achieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class Karma10Achieve 18 | */ 19 | class Karma10Achieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'Находчивый'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Набрать 10 кармы.'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/karma-10.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | Karma::created(function (Karma $karma) { 42 | 43 | $count = $karma->target->karma->count(); 44 | 45 | if ($count === 10) { 46 | $this->create($karma->target, $karma->created_at); 47 | } 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/Karma500Achieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class Karma500Achieve 18 | */ 19 | class Karma500Achieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'Рэмбо'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Набрать 500 кармы.'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/karma-500.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | Karma::created(function (Karma $karma) { 42 | $count = $karma->target->karma->count(); 43 | 44 | if ($count === 500) { 45 | $this->create($karma->target, $karma->created_at); 46 | } 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/Karma50Achieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class Karma50Achieve 18 | */ 19 | class Karma50Achieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'Любитель сладкого'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Набрать 50 кармы.'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/karma-50.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | Karma::created(function (Karma $karma) { 42 | $count = $karma->target->karma->count(); 43 | 44 | if ($count === 50) { 45 | $this->create($karma->target, $karma->created_at); 46 | } 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/ReaderAchieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class Thanks100Achieve 18 | */ 19 | class Thanks100Achieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'Вопрошайка'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Получить 100 раз ответ на свои вопросы.'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/thanks-100.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | Karma::created(function (Karma $karma) { 42 | $count = $karma->user->thanks->count(); 43 | 44 | if ($count === 100) { 45 | $this->create($karma->user, $karma->created_at); 46 | } 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/Thanks10Karma0Achieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class Thanks10Karma0Achieve 18 | */ 19 | class Thanks10Karma0Achieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'Полный паразец!'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Сказать 10 раз "спасибо" не имея ни единой благодарности.'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/thanks-10-karma-0.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | Karma::created(function (Karma $karma) { 42 | $userThanks = $karma->user->thanks->count(); 43 | $userKarma = $karma->user->karma->count(); 44 | 45 | if ($userThanks === 10 && $userKarma === 0) { 46 | $this->create($karma->user, $karma->created_at); 47 | } 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/Thanks20Achieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class Thanks20Achieve 18 | */ 19 | class Thanks20Achieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'Благодарный'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Высказать 20 благодарностей.'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/thanks-20.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | Karma::created(function (Karma $karma) { 42 | $count = $karma->user->thanks->count(); 43 | 44 | if ($count === 20) { 45 | $this->create($karma->user, $karma->created_at); 46 | } 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Domains/Bot/Achievements/Thanks50Achieve.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:07 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Bot\Achievements; 12 | 13 | use Domains\Karma; 14 | use Interfaces\Gitter\Achieve\AbstractAchieve; 15 | 16 | /** 17 | * Class Thanks50Achieve 18 | */ 19 | class Thanks50Achieve extends AbstractAchieve 20 | { 21 | /** 22 | * @var string 23 | */ 24 | public $title = 'Нахлебник'; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $description = 'Сказать 50 раз "спасибо".'; 30 | 31 | /** 32 | * @var string 33 | */ 34 | public $image = '//karma.laravel.su/img/achievements/thanks-50.gif'; 35 | 36 | /** 37 | * @throws \LogicException 38 | */ 39 | public function handle() 40 | { 41 | Karma::created(function (Karma $karma) { 42 | $count = $karma->user->thanks->count(); 43 | 44 | if ($count === 50) { 45 | $this->create($karma->user, $karma->created_at); 46 | } 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Domains/Bot/ClientInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 20.07.2016 15:34 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Domains\Bot; 13 | 14 | use Domains\Room\RoomInterface; 15 | use Domains\User; 16 | 17 | /** 18 | * Class AchieveSubscriber 19 | */ 20 | interface ClientInterface 21 | { 22 | /** 23 | * @param RoomInterface $room 24 | * @param string $message 25 | * 26 | * @return void 27 | */ 28 | public function sendMessage(RoomInterface $room, $message); 29 | 30 | /** 31 | * @param RoomInterface $room 32 | * 33 | * @return void 34 | */ 35 | public function listen(RoomInterface $room); 36 | 37 | /** 38 | * @return string 39 | */ 40 | public function version(); 41 | 42 | /** 43 | * @return ClientInterface 44 | */ 45 | public function run(): ClientInterface; 46 | 47 | /** 48 | * @param string $id 49 | * 50 | * @return User 51 | */ 52 | public function getUserById($id); 53 | } -------------------------------------------------------------------------------- /app/Domains/Bot/Middlewares/GoogleSearchMiddleware.php: -------------------------------------------------------------------------------- 1 | escaped_text; 19 | 20 | if (preg_match('/^(@.*?\s)?(?:погугли|загугли|гугли)\s(.*?)$/isu', $text, $matches)) { 21 | if (!trim($matches[2])) { 22 | return $message; 23 | } 24 | 25 | $hasMentions = count($message->mentions); 26 | $mention = null; 27 | 28 | if ($hasMentions) { 29 | $mention = $message->mentions[0]->isBot() 30 | ? $message->user 31 | : $message->mentions[0]; 32 | } 33 | 34 | $answer = trim($matches[1]) && $mention 35 | ? trans('google.personal', [ 36 | 'user' => $mention->login, 37 | 'query' => urlencode($matches[2]), 38 | ]) 39 | : trans('google.common', [ 40 | 'query' => urlencode($matches[2]), 41 | ]); 42 | 43 | $message->italic($answer); 44 | 45 | return null; 46 | } 47 | 48 | return $message; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/Domains/Bot/Middlewares/InlineDataMiddleware.php: -------------------------------------------------------------------------------- 1 | text); 21 | 22 | $isVideo = preg_match( 23 | '/[^`]http(?:s)?:\/\/(?:www\.)?(?:youtube\.com|youtu\.be).*?/iu' 24 | , ' ' . $message->text); 25 | 26 | if (($isImage || $isVideo) && ! $message->user->isBot()) { 27 | $answer = trans('gitter.inline', [ 28 | 'user' => $message->user->login 29 | ]); 30 | $message->italic($answer); 31 | } 32 | 33 | return $message; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Domains/Bot/Middlewares/KarmaCounterMiddleware.php: -------------------------------------------------------------------------------- 1 | validator = $validator; 29 | } 30 | 31 | /** 32 | * @param Message $message 33 | * @return mixed 34 | */ 35 | public function handle(Message $message) 36 | { 37 | if ($message->user->isBot()) { 38 | return $message; 39 | } 40 | 41 | $collection = $this->validator->validate($message); 42 | $hasAnswers = false; 43 | 44 | foreach ($collection as $state) { 45 | $user = $state->getUser(); 46 | 47 | if ($state->isIncrement()) { 48 | $message->user->addKarmaTo($user, $message); 49 | 50 | if ($user->isBot()) { 51 | $message->answer(trans('karma.bot', [ 52 | 'user' => $message->user->login 53 | ])); 54 | } 55 | } 56 | 57 | if (!$state->isNothing()) { 58 | $hasAnswers = true; 59 | $message->italic($state->getTranslation($user->karma_text)); 60 | } 61 | } 62 | 63 | if (!$hasAnswers) { 64 | return $message; 65 | } 66 | 67 | return Storage::SIGNAL_STOP; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/Domains/Bot/Middlewares/KarmaRenderMiddleware.php: -------------------------------------------------------------------------------- 1 | text)), trans('request.karma'), true)) { 21 | $args = [ 22 | 'user' => $message->user->login, 23 | 'karma' => $message->user->karma_text, 24 | 'thanks' => $message->user->thanks_text, 25 | ]; 26 | 27 | $karmaMessage = []; 28 | 29 | // Karma info 30 | $karmaMessage[] = $args['karma'] 31 | ? trans('karma.count.message', $args) 32 | : trans('karma.count.empty', $args); 33 | 34 | // If has achievements 35 | $achievements = $this->getAchievements($message); 36 | if ($achievements) { 37 | $karmaMessage[] = $achievements; 38 | } 39 | 40 | $groups = $message->getRoom()->groups(); 41 | 42 | if (in_array('karma', $groups)) { 43 | $karmaMessage[] = '[list]'; 44 | foreach ($groups as $group) { 45 | if (trans()->has($key = "karma.account.{$group}")) { 46 | $karmaMessage[] = trans($key, $args); 47 | } 48 | } 49 | $karmaMessage[] = '[/list]'; 50 | } 51 | 52 | $message->answer(implode("\n", $karmaMessage)); 53 | 54 | return null; 55 | } 56 | 57 | return $message; 58 | } 59 | 60 | /** 61 | * @param Message $message 62 | * @return null|string 63 | */ 64 | protected function getAchievements(Message $message) 65 | { 66 | $achievements = []; 67 | foreach ($message->user->achievements as $achieve) { 68 | $achievements[] = '"' . $achieve->title . '"'; 69 | } 70 | 71 | if (count($achievements)) { 72 | return trans('karma.achievements', [ 73 | 'achievements' => implode(', ', $achievements), 74 | ]); 75 | } 76 | 77 | return null; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/Domains/Bot/Middlewares/LaravelDocumentationSearcherMiddleware.php: -------------------------------------------------------------------------------- 1 | text_without_special_chars, $matches)) { 22 | 23 | if (!trim($query = $matches[3])) { 24 | return $message; 25 | } 26 | 27 | $client = new Client( 28 | '8BB87I11DE', 29 | '8e1d446d61fce359f69cd7c8b86a50de' 30 | ); 31 | 32 | $result = $client->initIndex('docs')->search($query); 33 | 34 | $response = ''; 35 | 36 | $hits = new Collection($result['hits']); 37 | 38 | $hits->unique(function ($row) { 39 | return $row['h1']; 40 | })->map(function ($row) { 41 | $row['link'] = 'https://laravel.com/docs/5.3/' . $row['link']; 42 | 43 | return $row; 44 | })->take(3)->each(function ($row) use (&$response) { 45 | $title = ''; 46 | foreach (['h1', 'h2', 'h3', 'h4', 'h5'] as $tag) { 47 | if (isset($row[$tag])) { 48 | $title .= ' ' . $row[$tag]; 49 | } 50 | } 51 | 52 | $response .= "[*] [i][url={$row['link']}]{$title}[/url][/i]" . PHP_EOL; 53 | }); 54 | 55 | if (!empty($response)) { 56 | $message->answer(trans('search.results', [ 57 | 'results' => '[list]' . PHP_EOL . $response . PHP_EOL . '[/list]', 58 | ])); 59 | } 60 | 61 | 62 | return null; 63 | } 64 | 65 | return $message; 66 | } 67 | 68 | /** 69 | * @return array 70 | */ 71 | public function getGroup() 72 | { 73 | return ['laravel', 'global']; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/Domains/Bot/Middlewares/LongMessageMiddleware.php: -------------------------------------------------------------------------------- 1 | text; 23 | $lines = count(explode("\n", $text)); 24 | $chars = mb_strlen($text); 25 | 26 | if (preg_match_all('/^((`{3}\s*)(\w+)?(\s*([\w\W]+?)\n*)\2)\n*(?:[^\S\w\s]|$)/m', $text, $matches)) { 27 | 28 | $codeLines = 0; 29 | 30 | foreach ($matches[5] as $code) { 31 | 32 | $codeLines += count(explode("\n", $code)); 33 | 34 | } 35 | 36 | if ($codeLines > self::MAX_CODE_LINES) { 37 | 38 | $answer = trans('long.code_personal', [ 39 | 'user' => $message->user->login, 40 | ]); 41 | 42 | $message->answer($answer); 43 | 44 | return null; 45 | } 46 | 47 | } elseif ($lines > self::MAX_LINES || $chars > self::MAX_CHARS) { 48 | 49 | $answer = trans('long.text_personal', [ 50 | 'user' => $message->user->login, 51 | ]); 52 | 53 | $message->italic($answer); 54 | 55 | return null; 56 | } 57 | 58 | return $message; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/Domains/Bot/Middlewares/MarkdownAdviserMiddleware.php: -------------------------------------------------------------------------------- 1 | escaped_text; 19 | 20 | if (preg_match('/^(@.*?\s)?(?:оформи\sкод|код\sоформи).*?$/isu', $text)) { 21 | 22 | $hasMentions = count($message->mentions); 23 | $mention = null; 24 | 25 | if ($hasMentions) { 26 | $mention = $message->mentions[0]->isBot() 27 | ? $message->user 28 | : $message->mentions[0]; 29 | } 30 | 31 | $answer = $mention 32 | ? trans('markdown.personal', [ 33 | 'user' => $mention->login, 34 | ]) 35 | : trans('markdown.common'); 36 | 37 | $message->italic($answer); 38 | 39 | return null; 40 | } 41 | 42 | return $message; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Domains/Bot/Middlewares/SqlBuilderMiddleware.php: -------------------------------------------------------------------------------- 1 | escaped_text; 21 | 22 | if (preg_match('/^(?:select|update|delete|drop|insert)/iu', $text)) { 23 | try { 24 | $builder = new BuilderClass($text); 25 | $message->code($builder->convert(), 'php'); 26 | 27 | return null; 28 | 29 | } catch (\Exception $e) { 30 | $message->pre('SQL Builder error: ' . $e->getMessage()); 31 | } 32 | } 33 | 34 | return $message; 35 | } 36 | 37 | /** 38 | * @return string|array 39 | */ 40 | public function getGroup() 41 | { 42 | return ['testing']; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Domains/Bot/TextParserInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 20.07.2016 15:34 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Domains\Bot; 13 | 14 | /** 15 | * Class AchieveSubscriber 16 | */ 17 | interface TextParserInterface 18 | { 19 | /** 20 | * @param string $message 21 | * 22 | * @return string 23 | */ 24 | public function parse(string $message); 25 | } -------------------------------------------------------------------------------- /app/Domains/BotManager.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 20.07.2016 17:08 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains; 12 | 13 | use Illuminate\Support\Manager; 14 | use Interfaces\Gitter\Client as GitterClient; 15 | use Interfaces\Slack\Client as SlackClient; 16 | 17 | /** 18 | * Class BotManager 19 | * @package Domains 20 | */ 21 | class BotManager extends Manager 22 | { 23 | /** 24 | * Get the default driver name. 25 | * 26 | * @return string 27 | */ 28 | public function getDefaultDriver() 29 | { 30 | return 'gitter'; 31 | } 32 | 33 | /** 34 | * @return \Illuminate\Foundation\Application|mixed 35 | */ 36 | public function createGitterDriver() 37 | { 38 | return new GitterClient($this->app['config']->get('gitter.token')); 39 | } 40 | 41 | /** 42 | * @return \Illuminate\Foundation\Application|mixed 43 | */ 44 | public function createSlackDriver() 45 | { 46 | return new SlackClient($this->app['config']->get('slack.token')); 47 | } 48 | } -------------------------------------------------------------------------------- /app/Domains/Message/FormatterInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 21.07.2016 10:00 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | namespace Domains\Message; 13 | 14 | interface FormatterInterface 15 | { 16 | /** 17 | * @param string $text 18 | * 19 | * @return string 20 | */ 21 | public function answer($text); 22 | 23 | /** 24 | * @param string $text 25 | * 26 | * @return string 27 | */ 28 | public function pre($text); 29 | 30 | /** 31 | * @param string $code 32 | * @param string $lang 33 | * 34 | * @return string 35 | */ 36 | public function code($code, $lang = ''); 37 | 38 | /** 39 | * @param string $text 40 | * 41 | * @return string 42 | */ 43 | public function italic($text); 44 | 45 | /** 46 | * @param string $text 47 | * 48 | * @return string 49 | */ 50 | public function bold($text); 51 | } 52 | -------------------------------------------------------------------------------- /app/Domains/Message/Message.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 28.03.2016 14:06 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | namespace Domains\Message; 13 | 14 | use Carbon\Carbon; 15 | use Core\Mappers\Message\MessageMapper; 16 | use Domains\Analyser\UrlFinder; 17 | 18 | /** 19 | * Class Message 20 | * @package Domains\Message 21 | * 22 | * @property-read $text 23 | * @property-read Carbon $created_at 24 | * @property-read Carbon $updated_at 25 | * @property-read array $words 26 | */ 27 | class Message extends MessageMapper 28 | { 29 | /** 30 | * @return string 31 | */ 32 | public function getId() 33 | { 34 | return $this->id; 35 | } 36 | 37 | /** 38 | * @return mixed 39 | */ 40 | public function getWordsAttribute() 41 | { 42 | $text = $this->text; 43 | 44 | $text = preg_replace('/```.*?```/su', '', $text); 45 | $text = preg_replace('/`.*?`/su', '', $text); 46 | $text = preg_replace(UrlFinder::getPattern(), '', $text); 47 | $text = preg_replace('/@[a-z0-9_@]+/iu', '', $text); 48 | 49 | preg_match_all('/\w+/iu', $text, $words, PREG_PATTERN_ORDER); 50 | 51 | return array_map(function ($word) { 52 | return mb_strtolower($word); 53 | }, $words[0]); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/Domains/Message/Relation.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 28.03.2016 18:07 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | namespace Domains\Message; 13 | 14 | use Core\Mappers\Message\RelationMapper; 15 | 16 | /** 17 | * Class Relation 18 | * @package Domains\Message 19 | * @property-read Message $answer 20 | * @property-read Message $question 21 | */ 22 | class Relation extends RelationMapper 23 | { 24 | /** 25 | * @return string 26 | */ 27 | public function getId() 28 | { 29 | return $this->id; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Domains/Message/Url.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 28.03.2016 14:35 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | namespace Domains\Message; 13 | 14 | use Core\Mappers\Message\UrlMapper; 15 | 16 | /** 17 | * Class Url 18 | * @property string $url 19 | * @package Domains\Message 20 | */ 21 | class Url extends UrlMapper 22 | { 23 | /** 24 | * @return string 25 | */ 26 | public function getId() 27 | { 28 | return $this->id; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Domains/Middleware/MiddlewareGroupableInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 20.07.2016 15:34 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Domains\Middleware; 12 | 13 | /** 14 | * Interface MiddlewareInterface 15 | */ 16 | interface MiddlewareGroupableInterface 17 | { 18 | /** 19 | * @return string|array 20 | */ 21 | public function getGroup(); 22 | } 23 | -------------------------------------------------------------------------------- /app/Domains/Middleware/MiddlewareInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 24.09.2015 15:34 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Domains\Middleware; 13 | 14 | use Domains\Message; 15 | 16 | /** 17 | * Interface MiddlewareInterface 18 | */ 19 | interface MiddlewareInterface 20 | { 21 | /** 22 | * @param $inputData 23 | * @return mixed 24 | */ 25 | public function handle(Message $inputData); 26 | } 27 | -------------------------------------------------------------------------------- /app/Domains/Room/RoomInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 20.07.2016 15:27 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Domains\Room; 13 | 14 | use Domains\Bot\ClientInterface; 15 | use Domains\Middleware\Storage; 16 | 17 | interface RoomInterface 18 | { 19 | /** 20 | * @return string 21 | */ 22 | public function id(); 23 | 24 | /** 25 | * @return string 26 | */ 27 | public function alias(); 28 | 29 | /** 30 | * @return array 31 | */ 32 | public function groups(); 33 | 34 | /** 35 | * @return string 36 | */ 37 | public function driver(); 38 | 39 | /** 40 | * @return ClientInterface 41 | */ 42 | public function client(); 43 | 44 | /** 45 | * @return Storage 46 | */ 47 | public function middleware(); 48 | 49 | /** 50 | * @return void 51 | */ 52 | public function listen(); 53 | 54 | /** 55 | * @param string $message 56 | */ 57 | public function sendMessage($message); 58 | } -------------------------------------------------------------------------------- /app/Domains/RoomManager.php: -------------------------------------------------------------------------------- 1 | 6 | * @author butschster 7 | * @date 09.10.2015 17:08 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | namespace Domains; 13 | 14 | use Domains\Room\RoomInterface; 15 | use Illuminate\Support\Collection; 16 | use Interfaces\Gitter\StandartGitterRoom; 17 | 18 | /** 19 | * Class RoomManager 20 | * @package Domains 21 | */ 22 | class RoomManager 23 | { 24 | /** 25 | * @var Collection 26 | */ 27 | protected $rooms; 28 | 29 | /** 30 | * RoomManager constructor. 31 | * 32 | * @param array $rooms 33 | */ 34 | public function __construct(array $rooms = []) 35 | { 36 | $this->rooms = new Collection(); 37 | } 38 | 39 | /** 40 | * @param RoomInterface $room 41 | * 42 | * @return $this 43 | */ 44 | public function register(RoomInterface $room) 45 | { 46 | $this->rooms->put($room->id(), $room); 47 | 48 | return $this; 49 | } 50 | 51 | /** 52 | * @param string $id 53 | * 54 | * @return RoomInterface|null 55 | */ 56 | public function get($id) 57 | { 58 | if (is_null($room = $this->rooms->get($id))) { 59 | return $this->rooms->filter(function(RoomInterface $room) use($id) { 60 | return $room->alias() == $id; 61 | })->first(); 62 | } 63 | 64 | return $room; 65 | } 66 | 67 | /** 68 | * @return array 69 | */ 70 | public function all() 71 | { 72 | return $this->rooms->all(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/Domains/Subscriber/Storage.php: -------------------------------------------------------------------------------- 1 | 6 | * @author butschster 7 | * @date 11.10.2015 8:26 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | namespace Domains\Subscriber; 13 | 14 | use Illuminate\Contracts\Container\Container; 15 | use Domains\Room\RoomInterface; 16 | 17 | /** 18 | * Class Storage 19 | */ 20 | class Storage 21 | { 22 | /** 23 | * @var SubscriberInterface[] 24 | */ 25 | protected $subscribers = []; 26 | 27 | /** 28 | * @var Container 29 | */ 30 | protected $container; 31 | 32 | /** 33 | * @var RoomInterface 34 | */ 35 | protected $room; 36 | 37 | /** 38 | * Storage constructor. 39 | * 40 | * @param Container $container 41 | * @param RoomInterface $room 42 | */ 43 | public function __construct(Container $container, RoomInterface $room) 44 | { 45 | $this->container = $container; 46 | $this->room = $room; 47 | } 48 | 49 | /** 50 | * @param $class 51 | * @return $this 52 | */ 53 | public function add($class) 54 | { 55 | $this->container->bind($class, $class); 56 | $subscriber = $this->container->make($class); 57 | 58 | $this->subscribers[] = $subscriber; 59 | 60 | $subscriber->handle($this->room); 61 | 62 | return $this; 63 | } 64 | } -------------------------------------------------------------------------------- /app/Domains/Subscriber/SubscriberInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * @author butschster 7 | * 8 | * @date 11.10.2015 8:27 9 | * 10 | * For the full copyright and license information, please view the LICENSE 11 | * file that was distributed with this source code. 12 | */ 13 | namespace Domains\Subscriber; 14 | 15 | use Domains\Room\RoomInterface; 16 | 17 | /** 18 | * Interface SubscriberInterface 19 | */ 20 | interface SubscriberInterface 21 | { 22 | /** 23 | * @param RoomInterface $room 24 | * 25 | * @return mixed 26 | */ 27 | public function handle(RoomInterface $room); 28 | } -------------------------------------------------------------------------------- /app/Domains/User/Mention.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 28.03.2016 14:25 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Domains\User; 14 | 15 | use Domains\Message\Message; 16 | 17 | /** 18 | * Class Mention 19 | * @package Domains\User 20 | * @property-read User $user 21 | * @property-read Message $message 22 | */ 23 | class Mention extends \Eloquent 24 | { 25 | /** 26 | * @var bool 27 | */ 28 | public $timestamps = false; 29 | 30 | /** 31 | * @var string 32 | */ 33 | protected $table = 'mentions'; 34 | 35 | /** 36 | * @return \Illuminate\Database\Eloquent\Relations\HasOne 37 | */ 38 | public function user() 39 | { 40 | return $this->hasOne(User::class, 'id', 'user_id'); 41 | } 42 | 43 | /** 44 | * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 45 | */ 46 | public function message() 47 | { 48 | return $this->belongsTo(Message::class, 'message_id', 'id'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/Domains/User/User.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 23.03.2016 20:17 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | namespace Domains\User; 13 | 14 | use Carbon\Carbon; 15 | use Domains\Message\Message; 16 | use Illuminate\Support\Collection; 17 | 18 | /** 19 | * Class User 20 | * TODO This class doesnot implemented Yet 21 | * 22 | * @package Domains\User 23 | * @property string $login 24 | * @property string $name 25 | * @property Carbon $created_at 26 | * @property Carbon $updated_at 27 | * @property-read Mention[]|Collection $mentions 28 | * @property-read Message[]|Collection $messages 29 | */ 30 | class User extends \Eloquent 31 | { 32 | /** 33 | * @var string 34 | */ 35 | protected $table = 'users'; 36 | 37 | /** 38 | * @return string 39 | */ 40 | public function getId() 41 | { 42 | return $this->id; 43 | } 44 | 45 | /** 46 | * @return \Illuminate\Database\Eloquent\Relations\HasMany 47 | */ 48 | public function mentions() 49 | { 50 | return $this->hasMany(Mention::class, 'user_id', 'id'); 51 | } 52 | 53 | /** 54 | * @return \Illuminate\Database\Eloquent\Relations\HasMany 55 | */ 56 | public function messages() 57 | { 58 | return $this->hasMany(Message::class, 'user_id', 'id'); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/Interfaces/Console/Commands/GetGitterRoomId.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 20.07.2016 14:44 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Interfaces\Console\Commands; 14 | 15 | use Gitter\Client; 16 | use Illuminate\Console\Command; 17 | 18 | /** 19 | * Class StartGitterBot 20 | */ 21 | class GetGitterRoomId extends Command 22 | { 23 | /** 24 | * The name and signature of the console command. 25 | * 26 | * @var string 27 | */ 28 | protected $signature = 'gitter:get-room-id {room}'; 29 | 30 | 31 | /** 32 | * The console command description. 33 | * 34 | * @var string 35 | */ 36 | protected $description = 'Get gitter room id by name.'; 37 | 38 | public function handle() 39 | { 40 | $client = new Client(\Config::get('gitter.token')); 41 | 42 | try { 43 | $result = $client->http->getRoomByUri($this->argument('room'))->wait(); 44 | $this->info("Room ID: {$result->id}"); 45 | } catch (\Exception $e) { 46 | $this->info('Room not found'); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /app/Interfaces/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('gitter:pool', ['restart']) 33 | ->everyFiveMinutes(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Interfaces/Gitter/Achieve/AchieveInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 11.10.2015 6:08 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Interfaces\Gitter\Achieve; 12 | 13 | /** 14 | * Interface AchieveInterface 15 | */ 16 | interface AchieveInterface 17 | { 18 | /** 19 | * @return mixed 20 | */ 21 | public function handle(); 22 | } -------------------------------------------------------------------------------- /app/Interfaces/Gitter/Ai.php: -------------------------------------------------------------------------------- 1 | getChannel($message->user) 25 | ->handle($message); 26 | } 27 | 28 | /** 29 | * @param User $user 30 | * @return UserChannel 31 | */ 32 | protected function getChannel(User $user) 33 | { 34 | $key = $user->gitter_id; 35 | if (!array_key_exists($key, $this->channels)) { 36 | $this->channels[$key] = new UserChannel($user); 37 | } 38 | return $this->channels[$key]; 39 | } 40 | } -------------------------------------------------------------------------------- /app/Interfaces/Gitter/Ai/UserChannel.php: -------------------------------------------------------------------------------- 1 | user = $user; 30 | } 31 | 32 | /** 33 | * @param Message $message 34 | */ 35 | public function handle(Message $message) 36 | { 37 | if ($this->has($message, ['привет', 'ку', 'здравствуй'])) { 38 | $this->answer($message, 'ну привет, коль не шутишь :)'); 39 | 40 | 41 | } else if ($this->has($message, 'как дела')) { 42 | $this->answer($message, 'пока не родила :trollface:'); 43 | 44 | 45 | } else if ($this->has($message, 'когда родишь')) { 46 | if ($this->lastAnswer === 'пока не родила :trollface:') { 47 | $this->answer($message, 'в процессе :D'); 48 | } else { 49 | $this->answer($message, 'м?'); 50 | } 51 | 52 | } else { 53 | $this->answer($message, $message->text_without_special_chars . '?'); 54 | } 55 | } 56 | 57 | /** 58 | * @param Message $message 59 | * @param $text 60 | * @return bool 61 | */ 62 | protected function has(Message $message, $text) 63 | { 64 | return Str::contains($message->text_without_special_chars, $text); 65 | } 66 | 67 | /** 68 | * @param Message $message 69 | * @param $text 70 | */ 71 | protected function answer(Message $message, $text) 72 | { 73 | $this->lastAnswer = $text; 74 | $message->italic(sprintf('@%s, ' . $text, $this->user->login)); 75 | } 76 | } -------------------------------------------------------------------------------- /app/Interfaces/Gitter/Console/CircleProgress.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 25.09.2015 16:43 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Interfaces\Gitter\Console; 14 | 15 | /** 16 | * Class CircleProgress 17 | */ 18 | class CircleProgress 19 | { 20 | /** 21 | * @var int 22 | */ 23 | protected $iterator = 0; 24 | 25 | /** 26 | * @var array 27 | */ 28 | protected static $icons = ['|', '/', '−', '\\']; 29 | 30 | /** 31 | * @return mixed 32 | */ 33 | public function get() 34 | { 35 | if ($this->iterator >= count(static::$icons)) { 36 | $this->iterator = 0; 37 | } 38 | 39 | return static::$icons[$this->iterator++]; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Interfaces/Gitter/Http/Request.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 24.09.2015 00:00 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Interfaces\Gitter\Http; 14 | 15 | use Interfaces\Gitter\Client; 16 | use GuzzleHttp\Client as Guzzle; 17 | use GuzzleHttp\Promise\PromiseInterface; 18 | 19 | /** 20 | * Class Request 21 | */ 22 | class Request 23 | { 24 | /** 25 | * @var array 26 | */ 27 | protected $callbacks = []; 28 | 29 | /** 30 | * @var string|mixed|string 31 | */ 32 | protected $url; 33 | 34 | /** 35 | * @var string 36 | */ 37 | protected $method; 38 | 39 | /** 40 | * @var array 41 | */ 42 | protected $headers; 43 | 44 | /** 45 | * @param Client $client 46 | * @param $route 47 | * @param array $args 48 | * @param string $method 49 | * @throws \InvalidArgumentException 50 | */ 51 | public function __construct(Client $client, $route, array $args, $method = 'GET') 52 | { 53 | $this->url = $client->getRouter()->route($route, $args); 54 | $this->method = $method; 55 | $this->headers = $client->getHeaders(); 56 | } 57 | 58 | /** 59 | * @param null $data 60 | * @return mixed|\Psr\Http\Message\ResponseInterface 61 | */ 62 | public function send($data = null) 63 | { 64 | return (new Guzzle)->request($this->method, $this->url, [ 65 | 'verify' => false, 66 | 'headers' => $this->headers, 67 | 68 | 'body' => is_array($data) || is_object($data) 69 | ? json_encode($data) 70 | : $data, 71 | ]); 72 | } 73 | 74 | /** 75 | * @param null $data 76 | * @return array 77 | */ 78 | public function sendParseJson($data = null): array 79 | { 80 | return json_decode($this->send($data)->getBody(), true); 81 | } 82 | 83 | /** 84 | * @param callable $callback 85 | * @return Request 86 | */ 87 | public function subscribe(callable $callback): Request 88 | { 89 | $this->callbacks[] = $callback; 90 | 91 | return $this; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /app/Interfaces/Gitter/StandartGitterRoom.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 20.07.2016 15:27 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Interfaces\Gitter; 13 | 14 | use Domains\Room\AbstractRoom; 15 | 16 | class StandartGitterRoom extends AbstractRoom 17 | { 18 | /** 19 | * AbstractRoom constructor. 20 | * 21 | * @param string $alias 22 | * @param string|array $groups 23 | * @param array $middleware 24 | */ 25 | public function __construct($alias, $groups = '*', array $middleware = []) 26 | { 27 | parent::__construct(); 28 | 29 | $this->alias = $alias; 30 | $this->groups = (array) $groups; 31 | 32 | $this->setMiddleware($middleware); 33 | } 34 | 35 | public function listen() 36 | { 37 | $result = $this->client()->getGitterClient()->http->getRoomByUri($this->alias())->wait(); 38 | $this->id = $result->id; 39 | 40 | parent::listen(); 41 | } 42 | 43 | /** 44 | * @return string 45 | */ 46 | public function id() 47 | { 48 | if (empty($this->id)) { 49 | return $this->alias(); 50 | } 51 | 52 | return parent::id(); 53 | } 54 | 55 | /** 56 | * @return string 57 | */ 58 | public function driver() 59 | { 60 | return 'gitter'; 61 | } 62 | } -------------------------------------------------------------------------------- /app/Interfaces/Gitter/Support/PriorityList.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 25.09.2015 14:47 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Interfaces\Gitter\Support; 14 | 15 | /** 16 | * Class PriorityList 17 | */ 18 | class PriorityList implements \IteratorAggregate 19 | { 20 | /** 21 | * @var [] 22 | */ 23 | protected $list = []; 24 | 25 | /** 26 | * @return PriorityList 27 | */ 28 | public function __construct() 29 | { 30 | $this->list = []; 31 | } 32 | 33 | /** 34 | * @param $value 35 | * @param int $priority 36 | * @return $this 37 | */ 38 | public function insert($value, $priority = 0) 39 | { 40 | if (!array_key_exists($priority, $this->list)) { 41 | $this->list[$priority] = []; 42 | krsort($this->list); 43 | } 44 | 45 | $this->list[$priority][] = $value; 46 | 47 | return $this; 48 | } 49 | 50 | /** 51 | * @return \Generator 52 | */ 53 | public function getIterator() 54 | { 55 | foreach ($this->list as $index => $priority) { 56 | foreach ($priority as $item) { 57 | yield $priority => $item; 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/Interfaces/Gitter/Support/StreamBuffer.php: -------------------------------------------------------------------------------- 1 | 7 | * @date 24.09.2015 00:00 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Interfaces\Gitter\Support; 14 | 15 | /** 16 | * Class StreamBuffer 17 | */ 18 | class StreamBuffer 19 | { 20 | /** 21 | * @var string 22 | */ 23 | protected $data = ''; 24 | 25 | /** 26 | * @var array 27 | */ 28 | protected $callbacks = []; 29 | 30 | /** 31 | * @param $chunk 32 | * @return StreamBuffer 33 | */ 34 | public function add($chunk): StreamBuffer 35 | { 36 | $chunks = explode("\n", $chunk); 37 | $count = count($chunks); 38 | 39 | if ($count === 1) { 40 | $this->data .= $chunk; 41 | 42 | } else { 43 | for ($i = 0; $i < $count; $i++) { 44 | $this->data .= $chunks[$i]; 45 | if ($i !== $count - 1) { 46 | $this->flush(); 47 | } 48 | } 49 | } 50 | 51 | return $this; 52 | } 53 | 54 | /** 55 | * @param callable|array $callback 56 | * @return StreamBuffer 57 | */ 58 | public function subscribe($callback): StreamBuffer 59 | { 60 | $this->callbacks[] = $callback; 61 | 62 | return $this; 63 | } 64 | 65 | /** 66 | * @return $this 67 | */ 68 | public function clear() 69 | { 70 | $this->data = ''; 71 | 72 | return $this; 73 | } 74 | 75 | /** 76 | * @return mixed|string 77 | */ 78 | public function flush(): string 79 | { 80 | $result = $this->data; 81 | $this->data = ''; 82 | 83 | foreach ($this->callbacks as $callback) { 84 | $callback($result); 85 | } 86 | 87 | return $result; 88 | } 89 | 90 | /** 91 | * @return mixed|integer 92 | */ 93 | public function size(): integer 94 | { 95 | return strlen($this->data); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/Interfaces/Gitter/UserMapper.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 09.10.2015 16:56 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Interfaces\Gitter; 13 | 14 | use Domains\User; 15 | use Interfaces\Gitter\Support\AttributeMapper; 16 | 17 | /** 18 | * Class UserMapper 19 | */ 20 | class UserMapper 21 | { 22 | /** 23 | * @param array|\StdClass $attributes 24 | * @return User 25 | * @throws InvalidArgumentException 26 | */ 27 | public static function fromGitterObject($attributes) 28 | { 29 | $values = (new AttributeMapper((array) $attributes)) 30 | ->rename('id', 'gitter_id') 31 | ->rename('username', 'login') 32 | ->rename('displayName', 'name') 33 | ->rename('avatarUrlMedium', 'avatar') 34 | ->only(['gitter_id', 'login', 'name', 'avatar', 'url']) 35 | ->toArray(); 36 | 37 | $user = User::where('gitter_id', $values['gitter_id'])->first(); 38 | if (!$user) { 39 | $user = User::unguarded(function () use ($values) { 40 | return User::create($values); 41 | }); 42 | } 43 | 44 | return $user; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/Interfaces/Http/Controllers/Api/AchievementsController.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 14.10.2015 11:21 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Interfaces\Http\Controllers\Api; 12 | 13 | use Domains\Achieve; 14 | use Illuminate\Support\Collection; 15 | use Interfaces\Http\Controllers\Controller; 16 | use Domains\Bot\AchieveSubscriber; 17 | use Interfaces\Gitter\Achieve\AbstractAchieve; 18 | 19 | /** 20 | * Class AchievementsController 21 | */ 22 | class AchievementsController extends Controller 23 | { 24 | /** 25 | * @return \Illuminate\Database\Eloquent\Collection|static[] 26 | */ 27 | public function index() 28 | { 29 | return \Cache::remember('achievements', 10, function () { 30 | $achieveStorage = []; 31 | 32 | (new Achieve()) 33 | ->selectRaw('name, count(user_id) as count') 34 | ->groupBy('name') 35 | ->get() 36 | ->each(function ($item) use (&$achieveStorage) { 37 | $achieveStorage[$item->name] = $item->count; 38 | }); 39 | 40 | return (new AchieveSubscriber()) 41 | ->toCollection() 42 | ->each(function (AbstractAchieve $achieve) use ($achieveStorage) { 43 | $achieve->users = $achieveStorage[$achieve->name] ?? 0; 44 | }) 45 | ->toArray(); 46 | }); 47 | } 48 | } -------------------------------------------------------------------------------- /app/Interfaces/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | \Interfaces\Http\Middleware\Authenticate::class, 30 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 31 | 'guest' => \Interfaces\Http\Middleware\RedirectIfAuthenticated::class, 32 | ]; 33 | } 34 | -------------------------------------------------------------------------------- /app/Interfaces/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | auth = $auth; 26 | } 27 | 28 | /** 29 | * Handle an incoming request. 30 | * 31 | * @param \Illuminate\Http\Request $request 32 | * @param \Closure $next 33 | * @return mixed 34 | */ 35 | public function handle($request, Closure $next) 36 | { 37 | if ($this->auth->guest()) { 38 | if ($request->ajax()) { 39 | return response('Unauthorized.', 401); 40 | } else { 41 | return redirect()->guest('auth/login'); 42 | } 43 | } 44 | 45 | return $next($request); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/Interfaces/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | auth = $auth; 26 | } 27 | 28 | /** 29 | * Handle an incoming request. 30 | * 31 | * @param \Illuminate\Http\Request $request 32 | * @param \Closure $next 33 | * @return mixed 34 | */ 35 | public function handle($request, Closure $next) 36 | { 37 | if ($this->auth->check()) { 38 | return redirect('/home'); 39 | } 40 | 41 | return $next($request); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Interfaces/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | where('user', '[a-zA-Z0-9_\-]+'); 7 | 8 | Route::get('/achievements', 'HomeController@index'); 9 | 10 | 11 | Route::group(['prefix' => 'api', 'namespace' => 'Api'], function () { 12 | // Users 13 | Route::get('users.json', 'UsersController@index'); 14 | Route::get('users/top.json', 'UsersController@getUsersTop'); 15 | Route::get('user/{gitterId}.json', 'UsersController@getUser'); 16 | 17 | // Achievements 18 | Route::get('achievements.json', 'AchievementsController@index'); 19 | 20 | 21 | Route::any('/{any}', function () { 22 | return ['error' => 'Not found']; 23 | })->where('any', '.*?'); 24 | }); 25 | 26 | 27 | Route::any('/{any}', function () { 28 | return Redirect::to('/'); 29 | })->where('any', '.*?'); -------------------------------------------------------------------------------- /app/Interfaces/Slack/MessageMapper.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 20.207.2016 17:08 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | namespace Interfaces\Slack; 12 | 13 | use Carbon\Carbon; 14 | use Domains\Room\RoomInterface; 15 | use Illuminate\Contracts\Support\Arrayable; 16 | use Interfaces\Gitter\Support\AttributeMapper; 17 | 18 | class MessageMapper implements Arrayable 19 | { 20 | /** 21 | * @var array 22 | */ 23 | protected $attributes; 24 | 25 | /** 26 | * MessageMapper constructor. 27 | * 28 | * @param RoomInterface $room 29 | * @param array $attributes 30 | */ 31 | public function __construct(RoomInterface $room, $attributes) 32 | { 33 | $fields = ['gitter_id', 'text', 'html', 'edited', 'user', 'unread', 34 | 'read_by', 'urls', 'mentions', 'issues', 'meta', 'created_at', 'updated_at', 'room_id']; 35 | 36 | $this->attributes = (new AttributeMapper($attributes)) 37 | ->rename('channel', 'room_id') 38 | ->value('user', function ($user) use($room) { 39 | return $room->client()->getUserById($user); 40 | }) 41 | ->value('ts', function ($date) { 42 | return Carbon::createFromTimestamp($date)->setTimezone('Europe/Moscow'); 43 | }, 'created_at') 44 | ->value('mentions', function ($ids) use($room) { 45 | $users = []; 46 | if (is_array($ids)) { 47 | foreach ($ids as $userId) { 48 | $users[] = $room->client()->getUserById($userId); 49 | } 50 | } 51 | 52 | return $users; 53 | }) 54 | ->only($fields) 55 | ->toArray(); 56 | 57 | if (!array_key_exists('room_id', $this->attributes)) { 58 | $this->attributes['room_id'] = $room->id(); 59 | } 60 | 61 | $this->attributes['gitter_id'] = md5($room->id()); 62 | } 63 | 64 | /** 65 | * Get the instance as an array. 66 | * 67 | * @return array 68 | */ 69 | public function toArray() 70 | { 71 | return $this->attributes; 72 | } 73 | } -------------------------------------------------------------------------------- /app/Interfaces/Slack/StandartSlackRoom.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 20.07.2016 15:27 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Interfaces\Slack; 13 | 14 | use Domains\Room\AbstractRoom; 15 | 16 | class StandartSlackRoom extends AbstractRoom 17 | { 18 | /** 19 | * AbstractRoom constructor. 20 | * 21 | * @param string $id 22 | * @param string|array $groups 23 | * @param array $middleware 24 | */ 25 | public function __construct($id, $groups = '*', array $middleware = []) 26 | { 27 | parent::__construct(); 28 | 29 | $this->id = $id; 30 | $this->alias = $id; 31 | $this->groups = (array) $groups; 32 | 33 | $this->setMiddleware($middleware); 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function driver() 40 | { 41 | return 'slack'; 42 | } 43 | } -------------------------------------------------------------------------------- /app/Interfaces/Slack/TextParser.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 09.10.2015 16:56 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Interfaces\Slack; 13 | 14 | class TextParser extends \Interfaces\Gitter\TextParser 15 | { 16 | 17 | /** 18 | * @brief Replaces BBCode urls. 19 | */ 20 | protected function replaceUrls() { 21 | 22 | $this->text = preg_replace_callback('%\[url\s*=\s*("(?:[^"]*")|\A[^\']*\Z|(?:[^\'">\]\s]+))\s*(?:[^]\s]*)\]([\W\D\w\s]*?)\[/url\]%iu', 23 | 24 | function ($matches) { 25 | if (isset($matches[1]) && isset($matches[2])) 26 | return "<".$matches[1]."|".$matches[2].">"; 27 | else 28 | throw new \RuntimeException(sprintf("Text identified by '%d' has malformed BBCode urls", $this->id)); 29 | }, 30 | 31 | $this->text 32 | ); 33 | 34 | } 35 | } -------------------------------------------------------------------------------- /app/Interfaces/Slack/UserMapper.php: -------------------------------------------------------------------------------- 1 | 6 | * @date 09.10.2015 16:56 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Interfaces\Slack; 13 | 14 | use Domains\User; 15 | use Interfaces\Gitter\Support\AttributeMapper; 16 | 17 | /** 18 | * Class UserMapper 19 | */ 20 | class UserMapper 21 | { 22 | /** 23 | * @param array|\StdClass $attributes 24 | * @return User 25 | * @throws InvalidArgumentException 26 | */ 27 | public static function fromSlackObject(\Slack\User $user) 28 | { 29 | $values = (new AttributeMapper((array) $user->data)) 30 | ->rename('id', 'gitter_id') 31 | ->rename('name', 'login') 32 | ->rename('real_name', 'name') 33 | ->value('profile', function($profile) { 34 | return $profile['image_48']; 35 | }, 'avatar') 36 | ->only(['gitter_id', 'login', 'name', 'avatar']) 37 | ->toArray(); 38 | 39 | $user = User::where('gitter_id', $values['gitter_id'])->first(); 40 | if (!$user) { 41 | $user = User::unguarded(function () use ($values) { 42 | return User::create($values); 43 | }); 44 | } 45 | 46 | return $user; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | make(Illuminate\Contracts\Console\Kernel::class); 32 | 33 | $status = $kernel->handle( 34 | $input = new Symfony\Component\Console\Input\ArgvInput, 35 | new Symfony\Component\Console\Output\ConsoleOutput 36 | ); 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Shutdown The Application 41 | |-------------------------------------------------------------------------- 42 | | 43 | | Once Artisan has finished running. We will fire off the shutdown events 44 | | so that any final work may be done by the application before we shut 45 | | down the process. This is the last thing to happen to the request. 46 | | 47 | */ 48 | 49 | $kernel->terminate($input, $status); 50 | 51 | exit($status); 52 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | Interfaces\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | Interfaces\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | Core\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /bootstrap/autoload.php: -------------------------------------------------------------------------------- 1 | =7.0", 12 | "laravel/framework": "5.1.*", 13 | "react/react": "^0.4.2", 14 | "react/socket-client": "^0.4.4", 15 | "react/http-client": "^0.4.6", 16 | "barryvdh/laravel-ide-helper": "2.1.*", 17 | "guzzlehttp/guzzle": "^6.1", 18 | "predis/predis": "~1.0", 19 | "serafim/evacuator": "1.0.*", 20 | "serafim/gitter-api": "2.0.*", 21 | "ramsey/uuid": "3.3.*", 22 | "doctrine/annotations": "1.2.*", 23 | "doctrine/dbal": "^2.5.0", 24 | "filp/whoops": "2.0.*", 25 | "php-ds/php-ds": "dev-master@dev", 26 | "big-shark/sql-to-builder": "dev-master@dev", 27 | "coderstephen/slack-client": "^0.2.4", 28 | "3f/converter": "^1.3", 29 | "algolia/algoliasearch-client-php": "^1.6.3" 30 | }, 31 | "require-dev": { 32 | "fzaninotto/faker": "~1.4", 33 | "mockery/mockery": "0.9.*", 34 | "phpunit/phpunit": "~4.0", 35 | "phpspec/phpspec": "~2.1" 36 | }, 37 | "autoload": { 38 | "classmap": [ 39 | "database" 40 | ], 41 | "files": [ 42 | "app/Core/Support/helpers.php" 43 | ], 44 | "psr-4": { 45 | "Core\\": "app/Core/", 46 | "Interfaces\\": "app/Interfaces/", 47 | "Domains\\": "app/Domains/", 48 | "Tests\\": "tests/" 49 | } 50 | }, 51 | "scripts": { 52 | "post-install-cmd": [ 53 | "php artisan clear-compiled", 54 | "php artisan optimize" 55 | ], 56 | "pre-update-cmd": [ 57 | "php artisan clear-compiled" 58 | ], 59 | "post-update-cmd": [ 60 | "php artisan ide-helper:generate", 61 | "php artisan optimize" 62 | ], 63 | "post-root-package-install": [ 64 | "php -r \"copy('.env.example', '.env');\"" 65 | ], 66 | "post-create-project-cmd": [ 67 | "php artisan key:generate" 68 | ] 69 | }, 70 | "minimum-stability": "dev", 71 | "prefer-stable": true, 72 | "config": { 73 | "preferred-install": "dist" 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /config/auth.php: -------------------------------------------------------------------------------- 1 | 'eloquent', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Authentication Model 23 | |-------------------------------------------------------------------------- 24 | | 25 | | When using the "Eloquent" authentication driver, we need to know which 26 | | Eloquent model should be used to retrieve your users. Of course, it 27 | | is often just the "User" model but you may use whatever you like. 28 | | 29 | */ 30 | 31 | 'model' => Domains\User::class, 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Authentication Table 36 | |-------------------------------------------------------------------------- 37 | | 38 | | When using the "Database" authentication driver, we need to know which 39 | | table should be used to retrieve your users. We have chosen a basic 40 | | default value but you may easily change it to any table you like. 41 | | 42 | */ 43 | 44 | 'table' => 'users', 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Password Reset Settings 49 | |-------------------------------------------------------------------------- 50 | | 51 | | Here you may set the options for resetting passwords including the view 52 | | that is your password reset e-mail. You can also set the name of the 53 | | table that maintains all of the reset tokens for your application. 54 | | 55 | | The expire time is the number of minutes that the reset token should be 56 | | considered valid. This security feature keeps tokens short-lived so 57 | | they have less time to be guessed. You may change this as needed. 58 | | 59 | */ 60 | 61 | 'password' => [ 62 | 'email' => 'emails.password', 63 | 'table' => 'password_resets', 64 | 'expire' => 60, 65 | ], 66 | 67 | ]; 68 | -------------------------------------------------------------------------------- /config/broadcasting.php: -------------------------------------------------------------------------------- 1 | env('BROADCAST_DRIVER', 'pusher'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Broadcast Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may define all of the broadcast connections that will be used 24 | | to broadcast events to other systems or over websockets. Samples of 25 | | each available type of connection are provided inside this array. 26 | | 27 | */ 28 | 29 | 'connections' => [ 30 | 31 | 'pusher' => [ 32 | 'driver' => 'pusher', 33 | 'key' => env('PUSHER_KEY'), 34 | 'secret' => env('PUSHER_SECRET'), 35 | 'app_id' => env('PUSHER_APP_ID'), 36 | ], 37 | 38 | 'redis' => [ 39 | 'driver' => 'redis', 40 | 'connection' => 'default', 41 | ], 42 | 43 | 'log' => [ 44 | 'driver' => 'log', 45 | ], 46 | 47 | ], 48 | 49 | ]; 50 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Cache Stores 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may define all of the cache "stores" for your application as 24 | | well as their drivers. You may even define multiple stores for the 25 | | same cache driver to group types of items stored in your caches. 26 | | 27 | */ 28 | 29 | 'stores' => [ 30 | 31 | 'apc' => [ 32 | 'driver' => 'apc', 33 | ], 34 | 35 | 'array' => [ 36 | 'driver' => 'array', 37 | ], 38 | 39 | 'database' => [ 40 | 'driver' => 'database', 41 | 'table' => 'cache', 42 | 'connection' => null, 43 | ], 44 | 45 | 'file' => [ 46 | 'driver' => 'file', 47 | 'path' => storage_path('framework/cache'), 48 | ], 49 | 50 | 'memcached' => [ 51 | 'driver' => 'memcached', 52 | 'servers' => [ 53 | [ 54 | 'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100, 55 | ], 56 | ], 57 | ], 58 | 59 | 'redis' => [ 60 | 'driver' => 'redis', 61 | 'connection' => 'default', 62 | ], 63 | 64 | ], 65 | 66 | /* 67 | |-------------------------------------------------------------------------- 68 | | Cache Key Prefix 69 | |-------------------------------------------------------------------------- 70 | | 71 | | When utilizing a RAM based store such as APC or Memcached, there might 72 | | be other applications utilizing the same cache. So, we'll specify a 73 | | value to get prefixed to all our keys so we can avoid collisions. 74 | | 75 | */ 76 | 77 | 'prefix' => 'laravel', 78 | 79 | ]; 80 | -------------------------------------------------------------------------------- /config/compile.php: -------------------------------------------------------------------------------- 1 | [ 17 | // 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled File Providers 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may list service providers which define a "compiles" function 26 | | that returns additional files that should be compiled, providing an 27 | | easy way to get common files from any packages you are utilizing. 28 | | 29 | */ 30 | 31 | 'providers' => [ 32 | // 33 | ], 34 | 35 | ]; 36 | -------------------------------------------------------------------------------- /config/google.php: -------------------------------------------------------------------------------- 1 | env('GOOGLE_TOKEN'), 5 | ]; -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | ], 21 | 22 | 'mandrill' => [ 23 | 'secret' => env('MANDRILL_SECRET'), 24 | ], 25 | 26 | 'ses' => [ 27 | 'key' => env('SES_KEY'), 28 | 'secret' => env('SES_SECRET'), 29 | 'region' => 'us-east-1', 30 | ], 31 | 32 | 'stripe' => [ 33 | 'model' => App\User::class, 34 | 'key' => env('STRIPE_KEY'), 35 | 'secret' => env('STRIPE_SECRET'), 36 | ], 37 | 38 | ]; 39 | -------------------------------------------------------------------------------- /config/slack.php: -------------------------------------------------------------------------------- 1 | env('SLACK_TOKEN', null), 5 | 6 | 'rooms' => [ 7 | env('SLACK_DEBUG_ROOM', null) => ['common', 'improvements'] 8 | ], 9 | 10 | 'middlewares' => [ 11 | 'common' => [ 12 | // Google поисковик 13 | Domains\Bot\Middlewares\NewGoogleSearchMiddleware::class, 14 | // Domains\Bot\Middlewares\GoogleSearchMiddleware::class, 15 | 16 | // Советник по оформлению сообщений 17 | Domains\Bot\Middlewares\MarkdownAdviserMiddleware::class, 18 | // Ответы на персональные вопросы для бота 19 | Domains\Bot\Middlewares\PersonalAnswersMiddleware::class, 20 | ], 21 | 22 | 'karma' => [ 23 | // Вывод кармы по запросу 24 | Domains\Bot\Middlewares\KarmaRenderMiddleware::class, 25 | // Подсчёт "спасибок" 26 | Domains\Bot\Middlewares\KarmaCounterMiddleware::class, 27 | ], 28 | 29 | 'improvements' => [ 30 | // Слишком длинные сообщения 31 | Domains\Bot\Middlewares\LongMessageMiddleware::class, 32 | 33 | // Анализ ссылок на изображения и видео 34 | // App\Middlewares\InlineDataMiddleware::class, 35 | ], 36 | ], 37 | ]; -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | realpath(base_path('resources/views')), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => realpath(storage_path('framework/views')), 32 | 33 | ]; 34 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | -------------------------------------------------------------------------------- /database/factories/ModelFactory.php: -------------------------------------------------------------------------------- 1 | define(App\User::class, function (Faker\Generator $faker) { 15 | return [ 16 | 'name' => $faker->name, 17 | 'email' => $faker->email, 18 | 'password' => bcrypt(str_random(10)), 19 | 'remember_token' => str_random(10), 20 | ]; 21 | }); 22 | -------------------------------------------------------------------------------- /database/migrations/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/database/migrations/.gitkeep -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $t->string('gitter_id')->index(); 18 | $t->string('name'); 19 | $t->string('avatar'); 20 | $t->string('url'); 21 | $t->string('login'); 22 | $t->string('email')->nullable()->unique(); 23 | $t->string('password', 60)->nullable(); 24 | $t->rememberToken(); 25 | $t->timestamps(); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::drop('users'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 17 | $table->string('token')->index(); 18 | $table->timestamp('created_at'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('password_resets'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2015_10_09_201137_create_karma_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 23 | $t->string('room_id'); 24 | $t->string('message_id'); 25 | $t->integer('user_id')->index(); 26 | $t->integer('user_target_id')->index(); 27 | $t->enum('status', $stats)->default('inc'); 28 | $t->timestamp('created_at'); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::drop('karma'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /database/migrations/2015_10_11_055740_create_achievements_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $t->string('name')->index(); 18 | $t->integer('user_id')->index(); 19 | $t->string('title'); 20 | $t->string('description'); 21 | $t->string('image'); 22 | $t->timestamp('created_at'); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::drop('achievements'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2015_10_14_165107_remove_negative_karma.php: -------------------------------------------------------------------------------- 1 | dropColumn('status'); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function down() 26 | { 27 | Schema::table('karma', function(Blueprint $t){ 28 | $stats = [ 29 | 'inc', 30 | 'dec' 31 | ]; 32 | 33 | $t->enum('status', $stats)->default('inc'); 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2015_10_15_204513_remove_unused_achievement_fields.php: -------------------------------------------------------------------------------- 1 | dropColumn([ 17 | 'image', 18 | 'title', 19 | 'description' 20 | ]); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::table('achievements', function(Blueprint $t) { 32 | $t->string('title'); 33 | $t->string('description'); 34 | $t->string('image'); 35 | }); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2016_04_09_034004_create_messages_table.php: -------------------------------------------------------------------------------- 1 | uuid('id')->unique()->primary(); 20 | $t->string('gitter_id')->index(); 21 | $t->uuid('room_id')->index(); 22 | $t->uuid('user_id')->index(); 23 | $t->longText('text'); 24 | $t->longText('text_rendered'); 25 | $t->timestamps(); 26 | }); 27 | 28 | Schema::create('urls', function(Blueprint $t) { 29 | $t->uuid('id')->unique()->primary(); 30 | $t->uuid('message_id')->index(); 31 | $t->string('url'); 32 | }); 33 | 34 | Schema::create('mentions', function(Blueprint $t) { 35 | $t->uuid('id')->unique()->primary(); 36 | $t->uuid('message_id')->index(); 37 | $t->uuid('user_id')->index(); 38 | }); 39 | 40 | Schema::create('message_relations', function(Blueprint $t) { 41 | $t->uuid('message_id')->index(); 42 | $t->uuid('answer_id')->index(); 43 | }); 44 | } 45 | 46 | /** 47 | * Reverse the migrations. 48 | * 49 | * @return void 50 | */ 51 | public function down() 52 | { 53 | Schema::drop('urls'); 54 | Schema::drop('messages'); 55 | Schema::drop('mentions'); 56 | Schema::drop('message_relations'); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /database/seeds/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/database/seeds/.gitkeep -------------------------------------------------------------------------------- /database/seeds/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | name, 'KarmaAchieve')) { 23 | $a->name = KarmaAchieve::class; 24 | } else if (strstr($a->name, 'Karma50Achieve')) { 25 | $a->name = Karma50Achieve::class; 26 | } else if (strstr($a->name, 'Karma100Achieve')) { 27 | $a->name = Karma100Achieve::class; 28 | } else if (strstr($a->name, 'Karma500Achieve')) { 29 | $a->name = Karma500Achieve::class; 30 | } 31 | $a->save(); 32 | } 33 | 34 | // $this->call(UserTableSeeder::class); 35 | 36 | Model::reguard(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var builder = require('lightweb-builder').default; 3 | 4 | 5 | gulp.task('scripts', function() { 6 | (new builder) 7 | .withGzip() 8 | .withMinify() 9 | .withPolyfill() 10 | .withCommonJs() 11 | .withSourceMaps() 12 | .then.js(function(compiler) { 13 | compiler 14 | .file(require.resolve('knockout/build/output/knockout-latest')) 15 | .file(require.resolve('jquery/dist/jquery')) 16 | }) 17 | .then.es7(function(compiler) { 18 | compiler 19 | .plugin('syntax-flow') 20 | .plugin('transform-flow-strip-types') 21 | .namespace('/') 22 | .path('resources/javascripts/'); 23 | }) 24 | .build('./public/assets/app.js'); 25 | }); 26 | 27 | 28 | gulp.task('styles', function () { 29 | (new builder) 30 | .withGzip() 31 | .withMinify() 32 | .withSourceMaps() 33 | .scss(function(compiler) { 34 | compiler 35 | .file('resources/stylesheets/layout.scss') 36 | .autoPrefix(); 37 | }) 38 | .build('./public/assets/app.css'); 39 | }); 40 | 41 | 42 | gulp.task('default', ['scripts', 'styles'], function () { 43 | 44 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "babel-plugin-syntax-flow": "^6.5.0", 5 | "babel-plugin-transform-flow-strip-types": "^6.7.0", 6 | "gulp": "3.9.*", 7 | "lightweb-builder": "0.0.*" 8 | }, 9 | "devDependencies": { 10 | "jquery": "^2.1.4", 11 | "knockout": "^3.3.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./tests/ 14 | 15 | 16 | 17 | 18 | app/ 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Redirect Trailing Slashes If Not A Folder... 9 | RewriteCond %{REQUEST_FILENAME} !-d 10 | RewriteRule ^(.*)/$ /$1 [L,R=301] 11 | 12 | # Handle Front Controller... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_FILENAME} !-f 15 | RewriteRule ^ index.php [L] 16 | 17 | -------------------------------------------------------------------------------- /public/assets/app.css.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/assets/app.css.gz -------------------------------------------------------------------------------- /public/assets/app.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/assets/app.js.gz -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/favicon.ico -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/favicon.png -------------------------------------------------------------------------------- /public/fonts/fa/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fa/FontAwesome.otf -------------------------------------------------------------------------------- /public/fonts/fa/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fa/fontawesome-webfont.eot -------------------------------------------------------------------------------- /public/fonts/fa/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fa/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /public/fonts/fa/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fa/fontawesome-webfont.woff -------------------------------------------------------------------------------- /public/fonts/fa/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fa/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Bold.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Bold.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Bold.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Bold.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-BoldItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-BoldItalic.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-BoldItalic.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-BoldItalic.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-BoldItalic.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Book.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Book.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Book.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Book.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Book.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Book.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Book.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Book.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-BookItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-BookItalic.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-BookItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-BookItalic.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-BookItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-BookItalic.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-BookItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-BookItalic.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraBold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraBold.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraBold.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraBold.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraBold.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraBoldItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraBoldItalic.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraBoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraBoldItalic.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraBoldItalic.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraLight.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraLight.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraLight.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraLight.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraLight.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraLight.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraLight.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraLightItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraLightItalic.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraLightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraLightItalic.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraLightItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraLightItalic.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-ExtraLightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-ExtraLightItalic.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Heavy.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Heavy.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Heavy.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Heavy.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Heavy.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Heavy.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Heavy.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Heavy.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-HeavyItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-HeavyItalic.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-HeavyItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-HeavyItalic.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-HeavyItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-HeavyItalic.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-HeavyItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-HeavyItalic.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Italic.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Italic.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Italic.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Italic.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Light.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Light.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Light.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Light.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-LightItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-LightItalic.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-LightItalic.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-LightItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-LightItalic.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-LightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-LightItalic.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Medium.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Medium.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Medium.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Medium.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-MediumItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-MediumItalic.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-MediumItalic.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-MediumItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-MediumItalic.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-MediumItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-MediumItalic.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Regular.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Regular.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Regular.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-Regular.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-SemiBold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-SemiBold.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-SemiBold.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-SemiBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-SemiBold.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-SemiBold.woff2 -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-SemiBoldItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-SemiBoldItalic.eot -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-SemiBoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-SemiBoldItalic.woff -------------------------------------------------------------------------------- /public/fonts/fira-4.1/FiraSans-SemiBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/fonts/fira-4.1/FiraSans-SemiBoldItalic.woff2 -------------------------------------------------------------------------------- /public/img/achievements/docs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/docs.gif -------------------------------------------------------------------------------- /public/img/achievements/grumbler.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/grumbler.gif -------------------------------------------------------------------------------- /public/img/achievements/karma-10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/karma-10.gif -------------------------------------------------------------------------------- /public/img/achievements/karma-100.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/karma-100.gif -------------------------------------------------------------------------------- /public/img/achievements/karma-1000.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/karma-1000.gif -------------------------------------------------------------------------------- /public/img/achievements/karma-50.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/karma-50.gif -------------------------------------------------------------------------------- /public/img/achievements/karma-500.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/karma-500.gif -------------------------------------------------------------------------------- /public/img/achievements/reader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/reader.gif -------------------------------------------------------------------------------- /public/img/achievements/thanks-10-karma-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/thanks-10-karma-0.gif -------------------------------------------------------------------------------- /public/img/achievements/thanks-100.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/thanks-100.gif -------------------------------------------------------------------------------- /public/img/achievements/thanks-20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/thanks-20.gif -------------------------------------------------------------------------------- /public/img/achievements/thanks-50.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/achievements/thanks-50.gif -------------------------------------------------------------------------------- /public/img/cloud-bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/cloud-bar.png -------------------------------------------------------------------------------- /public/img/events/newyear.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/events/newyear.gif -------------------------------------------------------------------------------- /public/img/laravel-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/public/img/laravel-logo.png -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | /* 10 | |-------------------------------------------------------------------------- 11 | | Register The Auto Loader 12 | |-------------------------------------------------------------------------- 13 | | 14 | | Composer provides a convenient, automatically generated class loader for 15 | | our application. We just need to utilize it! We'll simply require it 16 | | into the script here so that we don't have to worry about manual 17 | | loading any of our classes later on. It feels nice to relax. 18 | | 19 | */ 20 | 21 | require __DIR__.'/../bootstrap/autoload.php'; 22 | 23 | /* 24 | |-------------------------------------------------------------------------- 25 | | Turn On The Lights 26 | |-------------------------------------------------------------------------- 27 | | 28 | | We need to illuminate PHP development, so let us turn on the lights. 29 | | This bootstraps the framework and gets it ready for use, then it 30 | | will load up this application so that we can run it and send 31 | | the responses back to the browser and delight our users. 32 | | 33 | */ 34 | 35 | $app = require_once __DIR__.'/../bootstrap/app.php'; 36 | 37 | /* 38 | |-------------------------------------------------------------------------- 39 | | Run The Application 40 | |-------------------------------------------------------------------------- 41 | | 42 | | Once we have the application, we can handle the incoming request 43 | | through the kernel, and send the associated response back to 44 | | the client's browser allowing them to enjoy the creative 45 | | and wonderful application we have prepared for them. 46 | | 47 | */ 48 | 49 | $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); 50 | 51 | $response = $kernel->handle( 52 | $request = Illuminate\Http\Request::capture() 53 | ); 54 | 55 | $response->send(); 56 | 57 | $kernel->terminate($request, $response); 58 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /resources/achieve/achieve.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/resources/achieve/achieve.psd -------------------------------------------------------------------------------- /resources/achieve/icon-achieve-10.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/resources/achieve/icon-achieve-10.psd -------------------------------------------------------------------------------- /resources/achieve/vault.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/resources/achieve/vault.psd -------------------------------------------------------------------------------- /resources/javascripts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/resources/javascripts/.gitkeep -------------------------------------------------------------------------------- /resources/javascripts/Application.js: -------------------------------------------------------------------------------- 1 | import User from "/Models/User"; 2 | import Router from "/Lib/Router"; 3 | 4 | /** 5 | * Application 6 | */ 7 | export default class Application { 8 | /** 9 | * @type {Array} 10 | */ 11 | controllers = []; 12 | 13 | /** 14 | * @type {Router} 15 | */ 16 | router = Router; 17 | 18 | /** 19 | * @constructor 20 | */ 21 | constructor() { 22 | this.bootRoutes(); 23 | 24 | this.searchControllers(); 25 | 26 | User.load() 27 | .then((model: User) => { 28 | User.collection = User.collection 29 | .sort((user:User) => { 30 | return parseInt(user.thanks_count) || 0; 31 | }, -1) 32 | .sort((user:User) => { 33 | return parseInt(user.karma_count) || 0; 34 | }, -1); 35 | }) 36 | } 37 | 38 | bootRoutes() { 39 | this.router.add('/', 'home'); 40 | this.router.add('/user/{user}', 'user').where('user', '.*?'); 41 | this.router.add('/achievements', 'achievements'); 42 | 43 | this.router.boot(); 44 | } 45 | 46 | /** 47 | * @returns {Application} 48 | */ 49 | searchControllers() { 50 | [].slice.call(document.querySelectorAll('[data-controller]'), 0).forEach(node => { 51 | this.addController(node, node.getAttribute('data-controller')); 52 | }); 53 | return this; 54 | } 55 | 56 | /** 57 | * @param node 58 | * @param controller 59 | * @returns {Application} 60 | */ 61 | addController(node, controller) { 62 | this.controllers.push({ 63 | node: node, 64 | controller: controller 65 | }); 66 | return this; 67 | } 68 | 69 | /** 70 | * Boot application 71 | * 72 | * @returns {Application} 73 | */ 74 | run() { 75 | this.controllers.forEach(data => { 76 | var controller = require(data.controller.replace(/\\\/\./g, '/')); 77 | controller = controller.default || controller; 78 | ko.applyBindings(new controller(data.node), data.node); 79 | }); 80 | 81 | this.controllers = []; 82 | 83 | return this; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /resources/javascripts/Controllers/AchievementsController.js: -------------------------------------------------------------------------------- 1 | import Achieve from "/Models/Achieve"; 2 | import BaseController from "/Controllers/BaseController"; 3 | 4 | /** 5 | * 6 | */ 7 | export default class AchievementsController extends BaseController { 8 | /** 9 | * @type {string} 10 | */ 11 | static route = 'achievements'; 12 | 13 | /** 14 | * @type {*} 15 | */ 16 | achievements = ko.observableArray([]); 17 | 18 | /** 19 | * @constructor 20 | */ 21 | constructor() { 22 | super(); 23 | super.boot(); 24 | } 25 | 26 | /** 27 | * Show 28 | */ 29 | onShow() { 30 | Achieve.load().then((model: Achieve) => { 31 | this.achievements(model.items()); 32 | }); 33 | } 34 | } -------------------------------------------------------------------------------- /resources/javascripts/Controllers/BaseController.js: -------------------------------------------------------------------------------- 1 | import Router, {Route} from "/Lib/Router"; 2 | 3 | /** 4 | * Base Controller 5 | */ 6 | export default class BaseController { 7 | /** 8 | * @type {Function} 9 | */ 10 | visible = ko.observable(false); 11 | 12 | /** 13 | * @type {{}} 14 | */ 15 | args = {}; 16 | 17 | /** 18 | * Boot controller 19 | */ 20 | boot() { 21 | this.matchRouter(); 22 | 23 | if (!this.args) { 24 | this.args = {}; 25 | } 26 | 27 | this.visible.subscribe(state => { 28 | if (state && this.onShow) { 29 | this.onShow(this.args); 30 | } 31 | }); 32 | 33 | if (this.visible() && this.onShow) { 34 | this.onShow(this.args); 35 | } 36 | } 37 | 38 | /** 39 | * Router matches and event subscribe 40 | */ 41 | matchRouter() { 42 | Router.subscribe((route:Route) => { 43 | this.onRouteChange(route); 44 | }); 45 | } 46 | 47 | /** 48 | * @param route 49 | */ 50 | onRouteChange(route:Route) { 51 | this.visible(route.name === this.constructor.route); 52 | this.args = route.getStateArguments(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /resources/javascripts/Controllers/Partials/HeaderController.js: -------------------------------------------------------------------------------- 1 | import Router from "/Lib/Router"; 2 | 3 | /** 4 | * Header breadcrumbs 5 | */ 6 | export default class HeaderController { 7 | /** 8 | * Breadcrumbs title 9 | */ 10 | title = ko.observable(false); 11 | 12 | /** 13 | * Dropdown visibility 14 | */ 15 | dropdown = ko.observable(false); 16 | 17 | /** 18 | * @constructor 19 | */ 20 | constructor() { 21 | var title = document.querySelector('title'); 22 | var defaultTitle = title.innerHTML.trim(); 23 | 24 | this.title.subscribe(value => { 25 | title.innerHTML = value 26 | ? value 27 | : defaultTitle; 28 | }); 29 | 30 | Router.subscribe(route => { 31 | switch (route.name) { 32 | case 'user': 33 | this.title('Профиль @' + route.matches[1]); 34 | break; 35 | case 'achievements': 36 | this.title('Достижения'); 37 | break; 38 | default: 39 | this.title(false); 40 | } 41 | }); 42 | } 43 | 44 | /** 45 | * @returns {boolean} 46 | */ 47 | toggle() { 48 | this.dropdown(!this.dropdown()); 49 | return true; 50 | } 51 | 52 | /** 53 | * @returns {boolean} 54 | */ 55 | achievements() { 56 | Router.get('achievements').move(); 57 | return false; 58 | } 59 | 60 | /** 61 | * @returns {boolean} 62 | */ 63 | home() { 64 | Router.get('home').move(); 65 | return false; 66 | } 67 | } -------------------------------------------------------------------------------- /resources/javascripts/Controllers/Partials/RequestNotifiesController.js: -------------------------------------------------------------------------------- 1 | import Request from "/Lib/Request"; 2 | 3 | /** 4 | * 5 | */ 6 | export default class RequestNotifiesController { 7 | /** 8 | * @constructor 9 | */ 10 | constructor() { 11 | this.messages = Request.messages; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /resources/javascripts/Controllers/SearchController.js: -------------------------------------------------------------------------------- 1 | import User from "/Models/User"; 2 | import Config from "/Lib/Config"; 3 | import Router from "/Lib/Router"; 4 | import Request from "/Lib/Request"; 5 | import BaseController from "/Controllers/BaseController"; 6 | 7 | /** 8 | * 9 | */ 10 | export default class SearchController extends BaseController { 11 | /** 12 | * @type {string} 13 | */ 14 | static route = 'home'; 15 | 16 | /** 17 | * 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.query = ko.observable(''); 23 | this.users = ko.observableArray([]); 24 | 25 | this.query.subscribe(query => { 26 | query = query.toString().trim(); 27 | 28 | if (query.length) { 29 | var users = User.search(query) 30 | .each((user:User) => { 31 | user.doHighlight(query); 32 | }) 33 | .toArray(); 34 | 35 | 36 | this.users(users); 37 | } else { 38 | this.users([]); 39 | } 40 | }); 41 | 42 | super.boot(); 43 | } 44 | 45 | /** 46 | * @param user 47 | */ 48 | load(user: User) { 49 | user.profile(); 50 | return true; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /resources/javascripts/Controllers/UserController.js: -------------------------------------------------------------------------------- 1 | import User from "/Models/User"; 2 | import Router from "/Lib/Router"; 3 | import BaseController from "/Controllers/BaseController"; 4 | 5 | /** 6 | * 7 | */ 8 | export default class UserController extends BaseController { 9 | /** 10 | * @type {string} 11 | */ 12 | static route = 'user'; 13 | 14 | /** 15 | * @type {User} 16 | */ 17 | user = ko.observable(null); 18 | 19 | /** 20 | * @type {Function} 21 | */ 22 | error = ko.observable(null); 23 | 24 | /** 25 | * @constructor 26 | */ 27 | constructor() { 28 | super(); 29 | this.error.subscribe(value => { 30 | if (value) { 31 | setTimeout(() => { 32 | this.home(); 33 | }, 2000); 34 | } 35 | }); 36 | 37 | super.boot(); 38 | } 39 | 40 | /** 41 | * Show event 42 | */ 43 | onShow() { 44 | // Fix for window with empty args 45 | if (!this.args.user) { 46 | this.args.user = Router.current().matches[1]; 47 | } 48 | 49 | User.ready(state => { 50 | this.error(null); 51 | this.user(null); 52 | 53 | var user = User 54 | .query() 55 | .find((user:User) => user.route === this.args.user) 56 | .first(); 57 | 58 | if (!user) { 59 | this.error(`Страница ${this.args.user} не найдна.`); 60 | 61 | } else { 62 | try { 63 | user.loadProfile() 64 | .then((user:User) => this.user(user)); 65 | 66 | } catch (e) { 67 | console.log(e); 68 | this.error(`Пользователь ${this.args.user} не найден.`) 69 | } 70 | } 71 | }); 72 | } 73 | 74 | /** 75 | * Go to achievements page 76 | */ 77 | achievements() { 78 | Router.get('achievements').move(); 79 | } 80 | 81 | /** 82 | * Yankee go home! 83 | */ 84 | home() { 85 | Router.get('home').move(); 86 | } 87 | } -------------------------------------------------------------------------------- /resources/javascripts/Lib/Config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Config 3 | */ 4 | export default class Config { 5 | /** 6 | * @type {*|{}} 7 | */ 8 | static config = window.config || {}; 9 | 10 | /** 11 | * @param key 12 | * @returns {*|null} 13 | */ 14 | static get(key) { 15 | return this.config[key] || null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /resources/javascripts/Lib/Request/RequestMessage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Message 3 | */ 4 | export default class RequestMessage { 5 | /** 6 | * @type {number} 7 | */ 8 | static id = 0; 9 | 10 | /** 11 | * @type {string} 12 | */ 13 | text = ''; 14 | 15 | /** 16 | * @type {bool} 17 | */ 18 | visible = ko.observable(false); 19 | 20 | /** 21 | * @type {Array} 22 | */ 23 | events = []; 24 | 25 | /** 26 | * @constructor 27 | * @param text 28 | */ 29 | constructor(text) { 30 | this.id = RequestMessage.id++; 31 | this.text = text; 32 | this.visible(false); 33 | 34 | setTimeout(() => { 35 | this.visible(true); 36 | }, 200); 37 | 38 | this.visible.subscribe(state => { 39 | if (!state) { this.events.forEach((e) => e(this)); } 40 | }); 41 | } 42 | 43 | /** 44 | * @param callable 45 | * @returns {RequestMessage} 46 | */ 47 | onHide(callable) { 48 | this.events.push(callable); 49 | return this; 50 | } 51 | } -------------------------------------------------------------------------------- /resources/javascripts/Models/Achieve.js: -------------------------------------------------------------------------------- 1 | import Model from "/Lib/Model"; 2 | import Collection from "/Lib/Collection"; 3 | 4 | /** 5 | * Achieve 6 | */ 7 | export default class Achieve extends Model { 8 | /** 9 | * @type {string} 10 | */ 11 | static title = 'Достижения'; 12 | 13 | /** 14 | * @type {string} 15 | */ 16 | static request = '/api/achievements.json'; 17 | } 18 | -------------------------------------------------------------------------------- /resources/javascripts/Models/Karma.js: -------------------------------------------------------------------------------- 1 | import Model from "/Lib/Model"; 2 | import User from "/Models/User"; 3 | 4 | export default class Karma extends Model { 5 | constructor(properties = {}) { 6 | properties.user = User.find(u => u.id === properties.user_id).first(); 7 | super(properties); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /resources/javascripts/Models/Thank.js: -------------------------------------------------------------------------------- 1 | import Model from "/Lib/Model"; 2 | import User from "/Models/User"; 3 | 4 | export default class Thank extends Model { 5 | constructor(properties = {}) { 6 | properties.user = User.find(u => u.id === properties.user_target_id).first(); 7 | super(properties); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /resources/javascripts/Reflection/Serialize.js: -------------------------------------------------------------------------------- 1 | export default class Serialize { 2 | /** 3 | * @param value 4 | * @returns {string} 5 | */ 6 | static objectToString(value) { 7 | if (value instanceof Array) { 8 | return Serialize.arrayToString(value); 9 | } 10 | 11 | if (value instanceof Function) { 12 | return value.name; 13 | } 14 | 15 | if (typeof value === 'object') { 16 | var name = value.constructor.name; 17 | if (name !== 'Object') { 18 | return name; 19 | } 20 | 21 | var result = []; 22 | Object.keys(value).forEach(function (key) { 23 | result.push(key + ': ' + value[key].toString()); 24 | }); 25 | return '{' + result.join(', ') + '}'; 26 | 27 | } 28 | return value; 29 | } 30 | 31 | /** 32 | * @param result 33 | * @param before 34 | * @param after 35 | * @returns {string} 36 | */ 37 | static arrayToString(result = [], before = '', after = '') { 38 | return result 39 | .map(function (item) { 40 | return before + Serialize.objectToString(item) + after; 41 | }) 42 | .join(', '); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /resources/javascripts/Std/Abstract.js: -------------------------------------------------------------------------------- 1 | import Serialize from "/Reflection/Serialize"; 2 | 3 | /** 4 | * Sets abstract method or property 5 | * 6 | * @param context 7 | * @param name 8 | * @param descriptor 9 | * @returns {*} 10 | */ 11 | export default function Abstract(context, name, descriptor) { 12 | var declarationName = Serialize.objectToString(context) + '.' + descriptor.value.name; 13 | 14 | descriptor.value = function() { 15 | var contextName = Serialize.objectToString(this) + ' class'; 16 | throw new ReferenceError('Can not call an abstract method ' + declarationName + ' from ' + contextName); 17 | }; 18 | 19 | return descriptor; 20 | } 21 | -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/karma.php: -------------------------------------------------------------------------------- 1 | 'Add Like (+1) for [user]:user[/user]! Current karma level :karma.', 4 | 'decrement' => 'Dislike (-1) for [user]:user[/user]! Current karma level :karma.', 5 | 'timeout' => 'Karma for [user]:user[/user] not disturbed. Soooooo much karma-touchs :3', 6 | ]; -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Passwords must be at least six characters and match the confirmation.', 17 | 'reset' => 'Your password has been reset!', 18 | 'sent' => 'We have e-mailed your password reset link!', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that e-mail address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/en/request.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'karma', 6 | 'карма', 7 | ] 8 | ]; -------------------------------------------------------------------------------- /resources/lang/ru/achieve.php: -------------------------------------------------------------------------------- 1 | 4 | '> [h4]:title[/h4]' . "\n" . 5 | '> [user]:user[/user], вы выполнили условие: [i]":description"[/i].' . "\n" . 6 | '> С чем и поздравляем =)' . "\n" . 7 | '> [img]:image[/img]' 8 | ]; -------------------------------------------------------------------------------- /resources/lang/ru/gitter.php: -------------------------------------------------------------------------------- 1 | '[user]:user[/user], просьба оборачивать в [code]код[/code] ссылки на видео и изображения (используя обратные апострофы)', 4 | ]; 5 | -------------------------------------------------------------------------------- /resources/lang/ru/google.php: -------------------------------------------------------------------------------- 1 | [ 7 | 'погугли', 8 | 'загугли', 9 | 'гугли', 10 | 'почитай про', 11 | 'rtfm', 12 | ], 13 | 14 | 'personal' => '[user]:user[/user], [url=https://www.google.ru/webhp?#newwindow=1&hl=ru&q=:query]погуглил для тебя[/url]', 15 | 'common' => '[url=https://www.google.ru/webhp?#newwindow=1&hl=ru&q=:query]помог погуглить[/url]', 16 | 17 | 'results' => 'Можно поискать тут:', 18 | ]; 19 | -------------------------------------------------------------------------------- /resources/lang/ru/karma.php: -------------------------------------------------------------------------------- 1 | 'Спасибо (+1) для [user]:user[/user] принято! Текущая карма [b]:karma[/b].', 4 | 'timeout' => 'Карма [user]:user[/user] не потревожена. Слишком часто её пошатывали.', 5 | 'self' => 'Так не честно, [user]:user[/user]. Нельзя добавлять карму самому себе.', 6 | 'bot' => '[user]:user[/user], [i]не за что, я всегда к твоим услугам[/i] =)', 7 | 'nouser' => '[user]:user[/user], в этом чате принято добавлять имя пользователя, чтобы его поблагодарить.', 8 | 'achievements' => ' 9 | [list] 10 | [*] [i]Достижения: :achievements[/i] 11 | [/list]', 12 | 'account' => [ 13 | 'laravel' => ' [*] [i][url=http://karma.laravel.su/user/:user]Профиль :user на laravel.su[/url][/i]', 14 | 'yii' => ' [*] [i][url=http://karma.yiiframework.ru/user/:user]Профиль :user на yiiframework.ru[/url][/i]', 15 | ], 16 | 17 | 'count' => [ 18 | 'message' => '[user]:user[/user], [i]Ваша карма [b]:karma[/b]. Вы благодарили [b]:thanks[/b] раз.[/i]', 19 | 'empty' => '[user]:user[/user], [i]Вас ещё никто не благодарил.[/i]' 20 | ] 21 | ]; 22 | -------------------------------------------------------------------------------- /resources/lang/ru/long.php: -------------------------------------------------------------------------------- 1 | 5 | "[user]:user[/user], у нас тут принято писать кратко и по делу. А если нужно показать длинный код, то можно ". 6 | "использовать pastebin-сервис, например [url=https://gist.github.com/]gist.github.com[/url]". 7 | " или [url=http://laravel.io/bin]laravel.io/bin[/url]." 8 | , 9 | 'code_personal' => 10 | "[user]:user[/user], чтобы показать длинный листинг кода желательно использовать pastebin-сервис, например " . 11 | "[url=https://gist.github.com/]gist.github.com[/url] или [url=http://laravel.io/bin]laravel.io/bin[/url]." 12 | , 13 | ]; 14 | -------------------------------------------------------------------------------- /resources/lang/ru/markdown.php: -------------------------------------------------------------------------------- 1 | 5 | '[user]:user[/user], чтобы код легко читался, поставь [b]перед[/b] ним и [b]после[/b] него по строке с тремя обратными ' . 6 | 'апострофами (символ [pre] ` [/pre] на клавише с буквой «Ё»).' . "\n" . 7 | 'Узнать больше про оформление сообщений можно в справке по Markdown (кнопка [pre]M↓[/pre] внизу справа).' . "\n" . 8 | 'Кстати, свои сообщения здесь можно редактировать... ;)' 9 | , 10 | 11 | 'common' => 12 | 'Чтобы код легко читался, поставь [b]перед[/b] ним и [b]после[/b] него по строке с тремя обратными ' . 13 | 'апострофами (символ [pre] ` [/pre] на клавише с буквой «Ё»).' . "\n" . 14 | 'Узнать больше про оформление сообщений можно в справке по Markdown (кнопка [pre]M↓[/pre] внизу справа).' . "\n" . 15 | 'Кстати, свои сообщения здесь можно редактировать... ;)' 16 | , 17 | ]; 18 | -------------------------------------------------------------------------------- /resources/lang/ru/pagination.php: -------------------------------------------------------------------------------- 1 | '« Назад', 17 | 'next' => 'Вперёд »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/ru/personal.php: -------------------------------------------------------------------------------- 1 | [ 4 | 'добрый день', 5 | 'добрый вечер', 6 | 'доброй ночи', 7 | 'день добрый', 8 | 'вечер добрый', 9 | 'здравствуйте', 10 | 'приветствую', 11 | 'привет', 12 | 'даров', 13 | 'доброго времени суток', 14 | 'доброго утра', 15 | 'доброго дня', 16 | 'доброго вечера', 17 | 'прувет', 18 | 'бобрый', 19 | 'бобра', 20 | 'боброе', 21 | 'драсте', 22 | 'драсьте', 23 | 24 | // eng 25 | 26 | 'hello', 27 | 'hello world', 28 | 'hello guys', 29 | ], 30 | 'hello' => [ 31 | '[user]:user[/user], привет =)', 32 | '[user]:user[/user], и тебе привет ;)', 33 | '[user]:user[/user], здравствуй.', 34 | '[user]:user[/user], привет, как настроение?', 35 | '[user]:user[/user], ну рассказывай. Как жизнь? :)', 36 | '[user]:user[/user] даров!', 37 | '[user]:user[/user] и тебе не хворать :)', 38 | 'Приветствую тебя, [user]:user[/user]!', 39 | 'О! [user]:user[/user]! Сто лет не виделись!) Как жизнь молодецкая? Рассказывай :)', 40 | 'Не узнал тебя, [user]:user[/user]. Богатым будешь :)', 41 | 'Привет, [user]:user[/user]! Проходи, присаживайся. В ногах правды нет :)', 42 | 'Прувет, [user]:user[/user]!', 43 | 'Будь как дома, [user]:user[/user], я ни в чем не откажу. Много мануалов, коль желаешь, покажу :)', 44 | 45 | // eng 46 | 47 | 'Hello, [user]:user[/user]!', 48 | ], 49 | ]; 50 | -------------------------------------------------------------------------------- /resources/lang/ru/reminders.php: -------------------------------------------------------------------------------- 1 | 'Пароль должен быть не менее шести символов и совпадать с подтверждением.', 17 | 'user' => 'Не удалось найти пользователя с указанным электронным адресом.', 18 | 'token' => 'Ошибочный код сброса пароля.', 19 | 'sent' => 'Напоминание пароля отправлено!', 20 | 'reset' => 'Пароль был сброшен!', 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/ru/request.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'karma', 6 | 'карма', 7 | 'skill', 8 | 'скилл', 9 | 'ачивки', 10 | 11 | // other english 12 | 13 | 'attainment', 14 | 'achievement', 15 | 'progress', 16 | ] 17 | ]; 18 | -------------------------------------------------------------------------------- /resources/lang/ru/search.php: -------------------------------------------------------------------------------- 1 | 'По вашему запросу ничего не найдено', 5 | 'results' => '[i]Вот что нашел в документации:[/i] :results', 6 | ]; -------------------------------------------------------------------------------- /resources/stylesheets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelRUS/laravel-karma-bot/dfde57440276fc28fb183a1df945f814755993a3/resources/stylesheets/.gitkeep -------------------------------------------------------------------------------- /resources/stylesheets/layout/search.scss: -------------------------------------------------------------------------------- 1 | .search { 2 | padding: 30px 8px; 3 | 4 | input[type=text] { 5 | $height: ($ui-height * 2); 6 | line-height: $height; 7 | height: $height; 8 | width: 100%; 9 | font-size: 22px; 10 | padding: 0 30px; 11 | 12 | @include placeholder { 13 | font-weight: 100; 14 | } 15 | } 16 | 17 | h1 { 18 | display: block; 19 | } 20 | 21 | .search-error { 22 | text-align: center; 23 | } 24 | 25 | .search-description { 26 | color: #ccc; 27 | font-size: 28px; 28 | text-align: left; 29 | font-style: italic; 30 | transition: color .3s $swift; 31 | 32 | &:before { 33 | position: relative; 34 | margin: 0 15px 0 25px; 35 | top: -10px; 36 | @include fa-icon; 37 | transform: rotate(180deg); 38 | content: $fa-var-level-down; 39 | font-weight: 100; 40 | transition: margin .3s $swift; 41 | } 42 | } 43 | 44 | input:focus + .search-description { 45 | color: #999; 46 | } 47 | } -------------------------------------------------------------------------------- /resources/stylesheets/layout/users.scss: -------------------------------------------------------------------------------- 1 | .users { 2 | @include clear; 3 | 4 | .user { 5 | @include clear; 6 | float: left; 7 | border-radius: 2px; 8 | padding: 10px 10px; 9 | width: 530px; 10 | margin: 0 10px 30px 10px; 11 | background: #fff; 12 | position: relative; 13 | cursor: pointer; 14 | box-shadow: 0 0 0 2px rgba(#f4645f, 0); 15 | overflow: hidden; 16 | 17 | &:hover { 18 | transition: box-shadow .2s $swift; 19 | box-shadow: 0 0 0 2px #f4645f; 20 | } 21 | 22 | img { 23 | width: 80px; 24 | height: 80px; 25 | float: left; 26 | border-radius: 2px; 27 | margin: 0 10px 0 0; 28 | background: #f0f0f0; 29 | box-shadow: 0 0 0 2px #fff; 30 | } 31 | 32 | .highlight { 33 | color: darken(#f4645f, 20%); 34 | } 35 | 36 | .name, 37 | .login, 38 | nav { 39 | display: block; 40 | width: 420px; 41 | float: left; 42 | clear: right; 43 | white-space: nowrap; 44 | overflow: hidden; 45 | text-overflow: ellipsis; 46 | } 47 | 48 | .name, 49 | .login { 50 | font-weight: 300; 51 | color: #525252; 52 | font-size: 22px; 53 | } 54 | 55 | .name { 56 | font-size: 14px; 57 | } 58 | 59 | .user-karma{ 60 | position: absolute; 61 | right: 4px; 62 | top: 4px; 63 | width: 24px; 64 | height: 24px; 65 | color: #fff; 66 | background: #f4645f; 67 | border-radius: 2px; 68 | font-size: 12px; 69 | text-align: center; 70 | line-height: 25px; 71 | font-weight: 300; 72 | font-style: italic; 73 | } 74 | 75 | nav { 76 | margin-top: 10px; 77 | padding: 5px 0 0 0; 78 | box-shadow: 0 -1px 0 #dee0df; 79 | 80 | .separator, 81 | a { 82 | float: right; 83 | color: #888; 84 | text-decoration: none; 85 | } 86 | 87 | a:hover { 88 | color: #f4645f; 89 | text-decoration: underline; 90 | } 91 | 92 | .separator { 93 | font-weight: 100; 94 | margin: 0 10px; 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /resources/stylesheets/ui.scss: -------------------------------------------------------------------------------- 1 | $swift: cubic-bezier(.55, 0, .1, 1); 2 | 3 | $ui-height: 28px; 4 | $ui-min-height: 18px; 5 | $ui-mid-height: 36px; 6 | 7 | @import "ui/fonts"; 8 | @import "ui/labels"; 9 | @import "ui/inputs"; 10 | @import "ui/preloader"; 11 | -------------------------------------------------------------------------------- /resources/stylesheets/ui/inputs.scss: -------------------------------------------------------------------------------- 1 | input[type=text], 2 | input[type=password] { 3 | height: $ui-height; 4 | line-height: $ui-height; 5 | border-radius: 1px; 6 | padding: 0 10px; 7 | border: none; 8 | outline: none; 9 | box-shadow: 0 0 0 1px #dee0df; 10 | transition: .2s $swift; 11 | 12 | &:focus { 13 | box-shadow: 0 0 0 1px #f4645f; 14 | } 15 | } -------------------------------------------------------------------------------- /resources/stylesheets/ui/labels.scss: -------------------------------------------------------------------------------- 1 | .label { 2 | display: inline-block; 3 | line-height: $ui-height - 12px; 4 | min-height: $ui-height; 5 | vertical-align: baseline; 6 | margin: 0 .14285714em; 7 | background-color: #e8e8e8; 8 | padding: 6px .833em; 9 | color: rgba(#000, .6); 10 | text-transform: none; 11 | font-weight: 300; 12 | font-size: 12px; 13 | position: relative; 14 | border-radius: 2px; 15 | transition: background .1s ease; 16 | 17 | &.red { 18 | background-color: #db2828; 19 | color: #fff 20 | } 21 | 22 | &.orange { 23 | background-color: #f4645f; 24 | color: #fff; 25 | } 26 | 27 | &.yellow { 28 | background-color: #eaae00; 29 | color: #fff; 30 | } 31 | 32 | &.olive { 33 | background-color: #a7bd0d; 34 | color: #fff; 35 | } 36 | 37 | &.green { 38 | background-color: #16ab39; 39 | color: #fff; 40 | } 41 | 42 | &.teal { 43 | background-color: #009c95; 44 | color: #fff; 45 | } 46 | 47 | &.light-blue { 48 | background-color: #20b4d0; 49 | color: #fff; 50 | } 51 | 52 | &.blue { 53 | background-color: #1678c2; 54 | color: #fff; 55 | } 56 | 57 | &.violet { 58 | background-color: #5829bb; 59 | color: #fff; 60 | } 61 | 62 | &.purple { 63 | background-color: #9627ba; 64 | color: #fff; 65 | } 66 | 67 | &.pink { 68 | background-color: #e61a8d; 69 | color: #fff; 70 | } 71 | 72 | &.brown { 73 | background-color: #975b33; 74 | color: #fff; 75 | } 76 | 77 | &.black { 78 | background-color: #27292a; 79 | color: #fff; 80 | } 81 | } 82 | 83 | a.label { 84 | &:before { 85 | content: ''; 86 | background: rgba(#fff, 1); 87 | position: absolute; 88 | width: 100%; 89 | height: 100%; 90 | left: 0; 91 | top: 0; 92 | border-radius: 2px; 93 | transition: .3s $swift; 94 | opacity: 0; 95 | pointer-events: none; 96 | } 97 | 98 | &:hover { 99 | &:before { 100 | opacity: .3; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /resources/stylesheets/ui/preloader.scss: -------------------------------------------------------------------------------- 1 | @keyframes button-spin { 2 | from { 3 | transform: rotate(0deg); 4 | } 5 | 6 | to { 7 | transform: rotate(360deg) 8 | } 9 | } 10 | 11 | .preloader { 12 | width: auto; 13 | padding: 10px 15px; 14 | background: #f4645f; 15 | border-radius: 2px; 16 | color: #fff; 17 | position: fixed; 18 | right: 15px; 19 | bottom: 20px; 20 | opacity: 0; 21 | z-index: 9999; 22 | box-shadow: 0 2px 5px rgba(#000, .1); 23 | transition: 24 | opacity .3s $swift .3s, 25 | bottom .3s $swift .3s; 26 | 27 | &.visible { 28 | opacity: 1; 29 | bottom: 30px; 30 | transition: none; 31 | } 32 | 33 | &:after { 34 | content: ''; 35 | display: block; 36 | position: absolute; 37 | right: 15px; 38 | border: transparent 8px solid; 39 | border-top-color: #f4645f; 40 | bottom: -16px; 41 | } 42 | 43 | .circle { 44 | $size: 18px; 45 | 46 | position: relative; 47 | display: block; 48 | width: $size; 49 | height: $size; 50 | float: right; 51 | margin-left: 15px; 52 | 53 | &:before, 54 | &:after { 55 | position: absolute; 56 | content: ''; 57 | top: -2px; 58 | left: -2px; 59 | width: $size; 60 | height: $size; 61 | border-radius: 50%; 62 | box-shadow: 0 0 0 1px transparent; 63 | } 64 | 65 | &:before { 66 | border: rgba(#000, .4) 2px solid; 67 | } 68 | 69 | &:after { 70 | left: -2px; 71 | top: -2px; 72 | animation: button-spin .6s linear; 73 | animation-iteration-count: infinite; 74 | border: transparent 2px solid; 75 | border-left-color: #fff; 76 | } 77 | } 78 | } 79 | 80 | 81 | .preloader-section { 82 | $size: 32px; 83 | 84 | position: relative; 85 | display: block; 86 | width: 100%; 87 | height: $size; 88 | float: right; 89 | margin: 100px auto; 90 | 91 | &:after { 92 | position: absolute; 93 | content: ''; 94 | top: -2px; 95 | left: 50%; 96 | margin-left: (-$size / 2 - 2); 97 | width: $size; 98 | height: $size; 99 | border-radius: 50%; 100 | box-shadow: 0 0 0 1px transparent; 101 | } 102 | 103 | &:after { 104 | animation: button-spin .6s linear; 105 | animation-iteration-count: infinite; 106 | border: transparent 2px solid; 107 | border-left-color: #f4645f; 108 | } 109 | } -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome.scss: -------------------------------------------------------------------------------- 1 | $fa-font-path: "/fonts/fa"; 2 | $fa-css-prefix: icon; 3 | 4 | 5 | /*! 6 | * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome 7 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 8 | */ 9 | 10 | @import "font-awesome/variables"; 11 | @import "font-awesome/mixins"; 12 | @import "font-awesome/path"; 13 | @import "font-awesome/core"; 14 | @import "font-awesome/larger"; 15 | @import "font-awesome/fixed-width"; 16 | @import "font-awesome/list"; 17 | @import "font-awesome/bordered-pulled"; 18 | @import "font-awesome/animated"; 19 | @import "font-awesome/rotated-flipped"; 20 | @import "font-awesome/stacked"; 21 | @import "font-awesome/icons"; 22 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .pull-right { float: right; } 11 | .pull-left { float: left; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.pull-left { margin-right: .3em; } 15 | &.pull-right { margin-left: .3em; } 16 | } 17 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | 5 | .#{$fa-css-prefix} { 6 | display: inline-block; 7 | font: normal normal normal 14px/1 FontAwesome !important; // shortening font declaration 8 | font-size: inherit; // can't have font-size inherit on line above, so need to override 9 | text-rendering: auto; // optimizelegibility throws things off #1094 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal 14px/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | } 12 | 13 | @mixin fa-icon-rotate($degrees, $rotation) { 14 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 15 | -webkit-transform: rotate($degrees); 16 | -ms-transform: rotate($degrees); 17 | transform: rotate($degrees); 18 | } 19 | 20 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 21 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 22 | -webkit-transform: scale($horiz, $vert); 23 | -ms-transform: scale($horiz, $vert); 24 | transform: scale($horiz, $vert); 25 | } 26 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 9 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 10 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 11 | //src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 12 | font-weight: normal; 13 | font-style: normal; 14 | } 15 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/spinning.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | @-webkit-keyframes fa-spin { 10 | 0% { 11 | -webkit-transform: rotate(0deg); 12 | transform: rotate(0deg); 13 | } 14 | 100% { 15 | -webkit-transform: rotate(359deg); 16 | transform: rotate(359deg); 17 | } 18 | } 19 | 20 | @keyframes fa-spin { 21 | 0% { 22 | -webkit-transform: rotate(0deg); 23 | transform: rotate(0deg); 24 | } 25 | 100% { 26 | -webkit-transform: rotate(359deg); 27 | transform: rotate(359deg); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/font-awesome/stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /resources/stylesheets/vendor/utils.scss: -------------------------------------------------------------------------------- 1 | @mixin selection 2 | { 3 | &::selection { @content; } 4 | &::-moz-selection { @content; } 5 | } 6 | 7 | @mixin placeholder 8 | { 9 | &::-webkit-input-placeholder { @content; } 10 | &:-moz-placeholder { @content; } 11 | &::-moz-placeholder { @content; } 12 | &:-ms-input-placeholder { @content; } 13 | .placeholder { @content; } 14 | } 15 | 16 | 17 | /** 18 | * CLEARFIX 19 | */ 20 | 21 | @mixin clear($legacy: false) { 22 | @if $legacy { 23 | &:after { 24 | content: "\0020"; 25 | display: block; 26 | height: 0; 27 | clear: both; 28 | overflow: hidden; 29 | visibility: hidden; 30 | } 31 | *zoom: 1; 32 | } @else { 33 | &:after { 34 | display: table; 35 | width: 100%; 36 | content: ''; 37 | clear: both; 38 | } 39 | } 40 | } 41 | 42 | @mixin clearfix($legacy: false) { 43 | @include clear($legacy); 44 | } 45 | 46 | .clear { 47 | @include clear; 48 | } -------------------------------------------------------------------------------- /resources/views/home.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layout.master') 2 | 3 | @section('content') 4 | {{-- PARTIALS --}} 5 | @include('partials.notifies') 6 | @include('partials.header') 7 | 8 | {{-- PAGES --}} 9 | @include('page.search') 10 | @include('page.user') 11 | @include('page.achievements') 12 | @stop -------------------------------------------------------------------------------- /resources/views/layout/master.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | @section('title') Laravel Karma @show 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | @yield('content') 20 | 25 | 26 | -------------------------------------------------------------------------------- /resources/views/page/achievements.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

Все достижения

5 | 6 | 7 |
8 | 9 | 10 | 11 |
14 | 18 |

Achieve

19 |
description
20 | 21 | 22 | Получили человек 23 | 24 | 25 | Пока никто не получил 26 | 27 | 28 |
29 | 30 | 31 |
32 | 33 |
-------------------------------------------------------------------------------- /resources/views/page/search.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 14 | 15 | 16 |
17 | 18 | 47 | 48 |
49 |
-------------------------------------------------------------------------------- /resources/views/page/user.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | @include('page.user.profile') 16 | 17 | 18 | 19 |
-------------------------------------------------------------------------------- /resources/views/page/user/aside.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/views/partials/header.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 6 | 7 | 13 | 14 | 29 |
30 |
-------------------------------------------------------------------------------- /resources/views/partials/notifies.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 |
6 |
-------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | $uri = urldecode( 10 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 11 | ); 12 | 13 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 14 | // built-in PHP web server. This provides a convenient way to test a Laravel 15 | // application without having installed a "real" web server software here. 16 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 17 | return false; 18 | } 19 | 20 | require_once __DIR__.'/public/index.php'; 21 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /storage/assets/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | routes.php 3 | compiled.php 4 | services.json 5 | events.scanned.php 6 | routes.scanned.php 7 | down 8 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/pids/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/sync/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /tests/AbstractTestCase.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 26 | 27 | return $app; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/KarmaValidatorTest.php: -------------------------------------------------------------------------------- 1 | validator = new Validator(); 21 | 22 | $this->message = new Message(); 23 | $this->message->user = new User(); 24 | } 25 | 26 | /** 27 | * A basic functional test example. 28 | * 29 | * @return void 30 | */ 31 | public function testBasicExample() 32 | { 33 | 34 | } 35 | } 36 | --------------------------------------------------------------------------------