Commit 167892cb authored by nanahira's avatar nanahira

Merge branch 'v3-linux-touhou' into v3

parents a17c4a84 2fe2094d
......@@ -6,7 +6,7 @@ export class AppLocal {
path: string;
version: string;
files: Map<string, string>;
action: Map<string, {execute: string, args: string[], env: {}, open: App}>;
action: Map<string, {interpreter?: string, execute: string, args: string[], env: {}, open: App}>;
update(local: any) {
this.path = local.path;
......
import { AppLocal } from './app-local';
import * as path from 'path';
import * as ini from 'ini';
import * as fs from 'fs';
import * as child_process from 'child_process';
export enum Category {
game,
......@@ -21,12 +25,21 @@ export enum Category {
// uninstalling,
// waiting,
// }
export interface Action {
export interface BaseAction {
execute: string;
args: string[];
env: {};
}
export interface Action extends BaseAction {
interpreter?: string;
open?: App;
}
export interface SpawnAction extends BaseAction {
cwd?: string;
}
export class FileOptions {
sync: boolean;
ignore: boolean;
......@@ -213,4 +226,103 @@ export class App {
return dependencies.every((dependency) => dependency.isReady());
}
async getSpawnAction(children: App[], action_name = 'main', referencedApp?: App, referencedAction?: Action, cwd?: string): Promise<SpawnAction> {
const appCwd = (<AppLocal>this.local).path;
if(!cwd) {
cwd = appCwd;
}
if (this.id === 'np2fmgen') {
const config_file = path.join(this.local!.path, 'np21nt.ini');
let config = await new Promise((resolve, reject) => {
fs.readFile(config_file, {encoding: 'utf-8'}, (error, data) => {
if (error) {
return reject(error);
}
resolve(ini.parse(data));
});
});
const default_config = {
clk_mult: '48',
DIPswtch: '3e f3 7b',
SampleHz: '44100',
Latencys: '100',
MIX_TYPE: 'true',
windtype: '0'
};
config['NekoProject21'] = Object.assign({}, default_config, config['NekoProject21']);
config['NekoProject21']['HDD1FILE'] =
path.win32.join(process.platform === 'win32' ? '' : 'Z:', referencedApp.local!.path, referencedAction.execute);
config['NekoProject21']['fontfile'] =
path.win32.join(process.platform === 'win32' ? '' : 'Z:', referencedApp.local!.path, 'font.bmp');
await new Promise((resolve, reject) => {
fs.writeFile(config_file, ini.stringify(config), (error) => {
if (error) {
reject(error);
} else {
resolve(null);
}
});
});
cwd = appCwd;
}
let action: Action = <Action>this.actions.get(action_name);
let args: string[] = [];
let env = Object.assign({}, process.env);
for (let child of children) {
if (child.isInstalled()) {
let _action = child.actions.get(action_name);
if (_action) {
action = _action;
}
}
}
let execute: string;
const appExecute = path.join(cwd, action.execute);
if (action.interpreter) {
execute = action.interpreter;
args.push(appExecute);
} else {
execute = appExecute;
}
if (action.open) {
const np2 = action.open;
const openAction = await np2.getSpawnAction([], 'main', this, action, cwd);
args = args.concat(openAction.args);
args.push(action.execute);
execute = openAction.execute;
cwd = openAction.cwd;
}
args = args.concat(action.args);
env = Object.assign(env, action.env);
return {
execute,
args,
env,
cwd
}
}
async spawnApp(children: App[], action_name = 'main') {
if (this.id === 'th123') {
let th105 = <App>this.references.get('th105');
if (th105.isInstalled()) {
console.log(`Reference of th123: ${th105}`);
const config_file = path.join((<AppLocal>this.local).path, 'configex123.ini');
let config = ini.parse(await fs.promises.readFile(config_file, { encoding: 'utf-8' }));
const th105LocalApp = (<AppLocal>th105.local);
const targetTh105Path = th105LocalApp ? th105LocalApp.path : (<AppLocal>this.local).path.replace(/th123/g, 'th105');
config['th105path'] = {path: targetTh105Path};
await fs.promises.writeFile(config_file, ini.stringify(config));
}
}
const appCwd = (<AppLocal>this.local).path;
const {execute, args, env, cwd} = await this.getSpawnAction(children, action_name);
console.log(execute, args, env, cwd, appCwd);
return child_process.spawn(execute, args, {env: env, cwd: cwd || appCwd});
}
}
......@@ -763,100 +763,8 @@ export class AppsService {
async runApp(app: App, action_name = 'main') {
let children = this.findChildren(app);
let cwd = (<AppLocal>app.local).path;
let action: Action = <Action>app.actions.get(action_name);
let args: string[] = [];
let env = {};
for (let child of children) {
if (child.isInstalled()) {
let _action = child.actions.get(action_name);
if (_action) {
action = _action;
}
}
}
let execute = path.join(cwd, action.execute);
if (app.id === 'th123') {
let th105 = <App>app.references.get('th105');
if (th105.isInstalled()) {
const config_file = path.join((<AppLocal>app.local).path, 'configex123.ini');
let config = await new Promise((resolve, reject) => {
fs.readFile(config_file, {encoding: 'utf-8'}, (error, data) => {
if (error) {
return reject(error);
}
resolve(ini.parse(data));
});
});
config['th105path'] = {path: (<AppLocal>th105.local).path};
await new Promise((resolve, reject) => {
fs.writeFile(config_file, ini.stringify(config), (error) => {
if (error) {
reject(error);
} else {
resolve(null);
}
});
});
}
}
if (action.open) {
let np2 = action.open;
let openAction: Action;
openAction = np2.actions.get('main')!;
let openPath = np2.local!.path;
if (action.open.id === 'np2fmgen') {
const config_file = path.join(action.open!.local!.path, 'np21nt.ini');
let config = await new Promise((resolve, reject) => {
fs.readFile(config_file, {encoding: 'utf-8'}, (error, data) => {
if (error) {
return reject(error);
}
resolve(ini.parse(data));
});
});
const default_config = {
clk_mult: '48',
DIPswtch: '3e f3 7b',
SampleHz: '44100',
Latencys: '100',
MIX_TYPE: 'true',
windtype: '0'
};
config['NekoProject21'] = Object.assign({}, default_config, config['NekoProject21']);
config['NekoProject21']['HDD1FILE'] =
path.win32.join(process.platform === 'win32' ? '' : 'Z:', app.local!.path, action.execute);
config['NekoProject21']['fontfile'] =
path.win32.join(process.platform === 'win32' ? '' : 'Z:', app.local!.path, 'font.bmp');
await new Promise((resolve, reject) => {
fs.writeFile(config_file, ini.stringify(config), (error) => {
if (error) {
reject(error);
} else {
resolve(null);
}
});
});
if (process.platform !== 'win32') {
args.push(openAction.execute);
args = args.concat(openAction.args);
let wine = openAction.open!;
openPath = wine.local!.path;
openAction = openAction!.open!.actions.get('main')!;
}
cwd = np2.local!.path;
}
args = args.concat(openAction.args);
args.push(action.execute);
execute = path.join(openPath, openAction.execute);
env = Object.assign(env, openAction.env);
}
args = args.concat(action.args);
env = Object.assign(env, action.env);
console.log(execute, args, env, cwd);
let handle = child_process.spawn(execute, args, {env: env, cwd: cwd});
const handle = await app.spawnApp(children, action_name);
handle.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
......@@ -883,7 +791,7 @@ export class AppsService {
async network(app: App, server: any) {
if (!this.maotama) {
this.maotama = new Promise((resolve, reject) => {
let child = sudo.fork('maotama', [], {stdio: ['inherit', 'inherit', 'inherit', 'ipc']});
let child = (process.platform === 'linux' ? child_process : sudo).fork('maotama', [], {stdio: ['inherit', 'inherit', 'inherit', 'ipc']}); // it's very shit of Linux electron-sudo
child.once('message', () => resolve(child));
child.once('error', reject);
child.once('exit', reject);
......
......@@ -18,4 +18,4 @@
</div>
</div>
</div>
</div>
\ No newline at end of file
</div>
{
"name": "mycard",
"version": "3.0.47",
"version": "3.0.48",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "3.0.47",
"version": "3.0.48",
"hasInstallScript": true,
"license": "UNLICENSED",
"dependencies": {
......@@ -55,6 +55,7 @@
"@types/glob": "latest",
"@types/ini": "latest",
"@types/jquery": "^2.0.47",
"@types/lodash": "^4.14.172",
"@types/marked": "latest",
"@types/node": "^14.0.1",
"@types/tether": "latest",
......@@ -62,6 +63,7 @@
"electron": "^4.2.12",
"electron-builder": "latest",
"electron-builder-notarize": "^1.2.0",
"lodash": "^4.17.21",
"rollup": "latest",
"rollup-plugin-commonjs": "latest",
"rollup-plugin-node-resolve": "latest",
......@@ -544,6 +546,12 @@
"integrity": "sha512-QUJ5wVL8iTZofgZjCfVnHxcMqqPPLfVfEKe8rfksMdmSmqEenpcpEBQO45VSSfng/tunwoLF+3I8rzEzVhYNLQ==",
"dev": true
},
"node_modules/@types/lodash": {
"version": "4.14.172",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.172.tgz",
"integrity": "sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw==",
"dev": true
},
"node_modules/@types/marked": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.4.tgz",
......@@ -5878,6 +5886,12 @@
"integrity": "sha512-QUJ5wVL8iTZofgZjCfVnHxcMqqPPLfVfEKe8rfksMdmSmqEenpcpEBQO45VSSfng/tunwoLF+3I8rzEzVhYNLQ==",
"dev": true
},
"@types/lodash": {
"version": "4.14.172",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.172.tgz",
"integrity": "sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw==",
"dev": true
},
"@types/marked": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.4.tgz",
......
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=apps-json-type.js.map
\ No newline at end of file
{"version":3,"file":"apps-json-type.js","sourceRoot":"","sources":["apps-json-type.ts"],"names":[],"mappings":""}
\ No newline at end of file
export namespace AppsJson {
export interface Name {
'zh-CN': string;
'en-US': string;
}
export interface Description {
'zh-CN': string;
'en-US': string;
}
export interface ZhCN {
name: string;
url: string;
}
export interface Developers {
'zh-CN': ZhCN[];
}
export interface ZhCN2 {
name: string;
url: string;
}
export interface Publishers {
'zh-CN': ZhCN2[];
}
export interface Trailer {
type: string;
url: string;
url2: string;
}
export interface Dependencies {
win32: string[];
darwin: string[];
linux: any[];
}
export interface References {
win32: string[];
darwin: string[];
}
export interface Env {
}
export interface Action {
interpreter?: string;
execute: string;
args: any[];
env: Record<string, string>;
open: string;
}
export interface Env2 {
}
export interface Custom {
execute: string;
args: any[];
env: Env2;
}
export interface Install {
execute: string;
args: string[];
}
export interface Env3 {
}
export interface Network {
execute: string;
args: any[];
env: Env3;
}
export interface Env4 {
LANG: string;
WINEDEBUG: string;
}
export interface Main2 {
execute: string;
args: any[];
open: string;
env: Env4;
}
export interface Env5 {
LANG: string;
}
export interface Custom2 {
execute: string;
args: any[];
open: string;
env: Env5;
}
export interface Install2 {
execute: string;
args: string[];
open: string;
}
export interface Env6 {
LANG: string;
}
export interface Network2 {
execute: string;
args: any[];
open: string;
env: Env6;
}
export interface Env7 {
}
export interface Main3 {
execute: string;
args: any[];
env: Env7;
}
export interface Linux {
main: Main3;
}
export type PlatformAction = Record<string, Action>;
export interface Actions {
win32: PlatformAction;
darwin: PlatformAction;
linux: PlatformAction;
}
export interface Version {
win32: string;
darwin: string;
linux: string;
}
export interface Server {
id: string;
url: string;
}
export interface Network3 {
protocol: string;
port: number;
servers: Server[];
}
export interface DeckYdk {
sync: boolean;
}
export interface SingleLua {
sync: boolean;
}
export interface ReplayYrp {
sync: boolean;
}
export interface Files {
'deck/*.ydk': DeckYdk;
'single/*.lua': SingleLua;
'replay/*.yrp': ReplayYrp;
}
export interface Windbot {
'zh-CN': string[];
'en-US': string[];
}
export interface Data {
windbot: Windbot;
}
export interface Price {
cny: number;
usd: number;
}
export interface App {
id: string;
name: Name;
description: Description;
developers: Developers;
publishers: Publishers;
released_at: string;
category: string;
tags: string[];
trailer: Trailer[];
dependencies: Dependencies;
references: References;
author: string;
homepage: string;
locales: string[];
actions: Actions;
version: Version;
news: any;
conference: string;
icon: string;
cover: string;
background: string;
parent: string;
network: Network3;
updated_at: string;
files: Files;
data: Data;
price: Price;
}
}
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const _ = require("lodash");
function main() {
return __awaiter(this, void 0, void 0, function* () {
const apps = JSON.parse(yield fs_1.promises.readFile(process.argv[2], 'utf-8'));
for (const app of apps) {
console.log(`Reading ${app.id}`);
const actions = app.actions;
actions.linux = _.cloneDeep(actions.darwin);
for (const [actionName, action] of Object.entries(actions.linux)) {
if (action.open === 'wine') {
console.log(`Patching Linux action ${app.id}-${actionName}`);
action.open = undefined;
action.interpreter = 'wine';
}
}
}
yield fs_1.promises.writeFile(process.argv[2], JSON.stringify(apps, null, 2));
});
}
main();
//# sourceMappingURL=patch-linux-wine.js.map
\ No newline at end of file
{"version":3,"file":"patch-linux-wine.js","sourceRoot":"","sources":["patch-linux-wine.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2BAAoC;AAEpC,4BAA4B;AAE5B;;QACC,MAAM,IAAI,GAAmB,IAAI,CAAC,KAAK,CAAC,MAAM,aAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACrF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;YACvB,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;YAC5B,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC5C,KAAK,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBACjE,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE;oBAC3B,OAAO,CAAC,GAAG,CAAC,yBAAyB,GAAG,CAAC,EAAE,IAAI,UAAU,EAAE,CAAC,CAAC;oBAC7D,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC;oBACxB,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC;iBAC5B;aACD;SACD;QACD,MAAM,aAAE,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;CAAA;AACD,IAAI,EAAE,CAAC"}
\ No newline at end of file
import { promises as fs } from 'fs';
import { AppsJson } from './apps-json-type';
import * as _ from 'lodash';
async function main() {
const apps: AppsJson.App[] = JSON.parse(await fs.readFile(process.argv[2], 'utf-8'));
for (const app of apps) {
console.log(`Reading ${app.id}`);
const actions = app.actions;
actions.linux = _.cloneDeep(actions.darwin);
for (const [actionName, action] of Object.entries(actions.linux)) {
if (action.open === 'wine') {
console.log(`Patching Linux action ${app.id}-${actionName}`);
action.open = undefined;
action.interpreter = 'wine';
}
}
}
await fs.writeFile(process.argv[2], JSON.stringify(apps, null, 2));
}
main();
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