Commit b5d2229e authored by 神楽坂玲奈's avatar 神楽坂玲奈

匹配

parent acdc530c
......@@ -12,7 +12,7 @@ import { WatchComponent } from './watch/watch.component';
const routes: Routes = [
{
path: '',
canActivate: [AuthGuard],
canActivateChild: [AuthGuard],
children: [
{ path: '', redirectTo: '/ygopro/lobby', pathMatch: 'full' },
{ path: 'ygopro/rooms/new', component: NewRoomComponent },
......
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import { ActivatedRouteSnapshot, CanActivateChild, RouterStateSnapshot } from '@angular/router';
import { LoginService } from './login.service';
@Injectable()
export class AuthGuard implements CanActivate {
export class AuthGuard implements CanActivateChild {
constructor(private login: LoginService) {
}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
canActivateChild(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (this.login.user) {
return true;
}
const token = state.root.queryParamMap.get('sso') || new URL(location.href).searchParams.get('sso') || localStorage.getItem('login');
if (!token) {
alert('login required');
if (token) {
this.login.callback(token);
return true;
} else {
this.login.login();
return false;
}
this.login.sso(token);
return true;
}
}
......@@ -11,9 +11,9 @@
</md-option>
</md-autocomplete>
</form>
<button md-icon-button>
<a href="https://accounts.moecube.com/profiles" target="_blank" md-icon-button>
<img id="avatar" [src]="login.user.avatar_url">
</button>
</a>
<button md-icon-button [mdMenuTriggerFor]="menu">
<md-icon>add</md-icon>
......
......@@ -29,7 +29,7 @@ export class LobbyComponent {
constructor(public login: LoginService, public ygopro: YGOProService, public dialog: MdDialog, private http: Http, private jsonp: Jsonp, private route: ActivatedRoute) {
const arena_url = new URL('https://mycard.moe/ygopro/arena');
arena_url.searchParams.set('sso', login.token);
arena_url.searchParams.set('callback', login.token);
this.arena_url = arena_url.toString();
}
......
import { Injectable } from '@angular/core';
import { fromPairs } from 'lodash';
import { TextDecoder, TextEncoder } from 'text-encoding';
import { User } from './ygopro.service';
@Injectable()
......@@ -8,7 +9,43 @@ export class LoginService {
user: User;
token: string;
sso(token: string) {
login() {
let params = new URLSearchParams();
params.set('return_sso_url', location.href);
let payload = Buffer.from(params.toString()).toString('base64');
let url = new URL('https://accounts.moecube.com');
params = url['searchParams'];
params.set('sso', payload);
// const key = await window.crypto.subtle.importKey(
// 'jwk', //can be "jwk" or "raw"
// { //this is an example jwk key, "raw" would be an ArrayBuffer
// kty: 'oct',
// k: 'zsZv6LXHDwwtUAGa',
// alg: 'HS256',
// ext: true,
// },
// { //this is the algorithm options
// name: 'HMAC',
// hash: { name: 'SHA-256' }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
// //length: 256, //optional, if you want your key length to differ from the hash function's block length
// },
// false, //whether the key is extractable (i.e. can be used in exportKey)
// ['sign', 'verify'] //can be any combination of "sign" and "verify"
// );
//
// const sign = await window.crypto.subtle.sign(
// 'HMAC',
// key, //from generateKey or importKey above
// new TextEncoder().encode(payload) //ArrayBuffer of data you want to sign
// );
// console.log(Buffer.from(new TextDecoder().decode(sign)).toString('hex'));
// params.set('sig', crypto.createHmac('sha256', 'zsZv6LXHDwwtUAGa').update(payload).digest('hex'));
return location.replace(url.toString());
}
callback(token: string) {
this.token = token;
this.user = fromPairs(Array.from(new URLSearchParams(Buffer.from(token, 'base64').toString())));
localStorage.setItem('login', token);
......
import { Component, Inject } from '@angular/core';
import { Http } from '@angular/http';
import { MD_DIALOG_DATA } from '@angular/material';
import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
import { Headers, Http } from '@angular/http';
import { MD_DIALOG_DATA, MdDialogRef } from '@angular/material';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import { LoginService } from '../login.service';
import { YGOProService } from '../ygopro.service';
@Component({
selector: 'app-match',
templateUrl: './match.component.html',
styleUrls: ['./match.component.css']
})
export class MatchDialog {
export class MatchDialog implements OnInit, OnDestroy {
expect_wait = this.http.get('https://api.mycard.moe/ygopro/match/stats/' + this.arena).map(response => new Date(response.json() * 1000));
actual_wait = Observable.timer(0, 1000).map(timestamp => new Date(timestamp * 1000));
constructor(@Inject(MD_DIALOG_DATA) public arena: string, private http: Http) {
matching: Subscription;
constructor(@Inject(MD_DIALOG_DATA) public arena: string, private dialogRef: MdDialogRef<MatchDialog>, private http: Http, private login: LoginService, private ygopro: YGOProService) {
}
ngOnInit() {
this.matching = this.http.post('https://api.mycard.moe/ygopro/match', null, {
headers: new Headers({ Authorization: 'Basic ' + Buffer.from(this.login.user.username + ':' + this.login.user.external_id).toString('base64') }),
params: { arena: this.arena, locale: 'zh-CN' }
}).map(response => response.json()).subscribe((data) => {
this.ygopro.join(data['password'], { address: data['address'], port: data['port'] });
this.dialogRef.close();
}, (error) => {
alert(`匹配失败`);
this.dialogRef.close();
});
}
ngOnDestroy() {
this.matching.unsubscribe();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment