ct 0.10.8.114__py3-none-any.whl → 0.10.8.116__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cantools/__init__.py +38 -13
- cantools/_db.py +1 -1
- cantools/cfg.py +13 -0
- cantools/config.py +12 -4
- cantools/db/__init__.py +3 -0
- cantools/db/gae/model.py +1 -2
- cantools/db/wp.py +1 -1
- cantools/scripts/index.py +2 -8
- cantools/scripts/init.py +1 -1
- cantools/scripts/pubsub/actor.py +3 -1
- cantools/scripts/pubsub/bots.py +11 -13
- cantools/scripts/start.py +2 -2
- cantools/util/__init__.py +2 -0
- cantools/util/admin.py +10 -18
- cantools/util/ai/__init__.py +8 -0
- cantools/util/ai/tox/__init__.py +15 -0
- cantools/util/ai/tox/duck.py +80 -0
- cantools/util/ai/tox/fzn.py +22 -0
- cantools/util/ai/tox/g4free.py +73 -0
- cantools/util/ai/vox.py +84 -0
- cantools/util/apper/__init__.py +1 -0
- cantools/util/apper/ander.py +101 -0
- cantools/util/apper/data.py +167 -0
- cantools/util/system.py +2 -23
- cantools/web/__init__.py +6 -2
- cantools/web/bw.py +70 -0
- cantools/web/gae_server.py +1 -6
- cantools/web/util.py +6 -409
- {ct-0.10.8.114.dist-info → ct-0.10.8.116.dist-info}/METADATA +7 -8
- ct-0.10.8.116.dist-info/RECORD +56 -0
- cantools/web/dez_server/__init__.py +0 -1
- cantools/web/dez_server/controller.py +0 -129
- cantools/web/dez_server/cron.py +0 -115
- cantools/web/dez_server/daemons.py +0 -64
- cantools/web/dez_server/mail.py +0 -24
- cantools/web/dez_server/response.py +0 -63
- cantools/web/dez_server/routes.py +0 -21
- cantools/web/dez_server/server.py +0 -229
- cantools/web/dez_server/sms.py +0 -12
- ct-0.10.8.114.dist-info/RECORD +0 -55
- {ct-0.10.8.114.dist-info → ct-0.10.8.116.dist-info}/LICENSE +0 -0
- {ct-0.10.8.114.dist-info → ct-0.10.8.116.dist-info}/WHEEL +0 -0
- {ct-0.10.8.114.dist-info → ct-0.10.8.116.dist-info}/entry_points.txt +0 -0
- {ct-0.10.8.114.dist-info → ct-0.10.8.116.dist-info}/top_level.txt +0 -0
cantools/util/ai/vox.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import random
|
|
2
|
+
from ..system import cmd
|
|
3
|
+
|
|
4
|
+
class Kvox(object):
|
|
5
|
+
def __init__(self, log=print):
|
|
6
|
+
self.logger = log
|
|
7
|
+
self.kpipes = {}
|
|
8
|
+
|
|
9
|
+
def log(self, *msg):
|
|
10
|
+
self.logger("Kvox", *msg)
|
|
11
|
+
|
|
12
|
+
def getpipe(self, lang_code):
|
|
13
|
+
from kokoro import KPipeline
|
|
14
|
+
if lang_code not in self.kpipes:
|
|
15
|
+
self.kpipes[lang_code] = KPipeline(lang_code=lang_code)
|
|
16
|
+
return self.kpipes[lang_code]
|
|
17
|
+
|
|
18
|
+
def vi(self, t, v):
|
|
19
|
+
t = round(t)
|
|
20
|
+
self.log("viseme with time", t, "and value", v)
|
|
21
|
+
return { "time": t, "value": v }
|
|
22
|
+
|
|
23
|
+
def token2visemes(self, token, visemes):
|
|
24
|
+
self.log("token2visemes", token.text, token.phonemes, token.start_ts, token.end_ts)
|
|
25
|
+
phos = token.text # phonemes are full of unicode....
|
|
26
|
+
step = 1000 * (token.end_ts - token.start_ts) / len(phos)
|
|
27
|
+
t = 1000 * token.start_ts
|
|
28
|
+
for pho in phos:
|
|
29
|
+
visemes.append(self.vi(t, pho))
|
|
30
|
+
t += step
|
|
31
|
+
return t
|
|
32
|
+
|
|
33
|
+
def tokens2visemes(self, tokens):
|
|
34
|
+
self.log("tokens2visemes")
|
|
35
|
+
t = 0
|
|
36
|
+
visemes = []
|
|
37
|
+
for token in tokens:
|
|
38
|
+
t = self.token2visemes(token, visemes)
|
|
39
|
+
visemes.append(self.vi(t, "sil"))
|
|
40
|
+
return visemes
|
|
41
|
+
|
|
42
|
+
def __call__(self, text, voice="af_heart", speed=1, lang_code='a', filename="tts"):
|
|
43
|
+
import json, soundfile
|
|
44
|
+
pipeline = self.getpipe(lang_code)
|
|
45
|
+
nothing, tokens = pipeline.g2p(text)
|
|
46
|
+
for result in pipeline.generate_from_tokens(tokens=tokens, voice=voice, speed=float(speed)):
|
|
47
|
+
self.log(result.phonemes)
|
|
48
|
+
vz = self.tokens2visemes(result.tokens)
|
|
49
|
+
vname = "%s.json"%(filename,)
|
|
50
|
+
aname = "%s.mp3"%(filename,)
|
|
51
|
+
self.log("writing", vname)
|
|
52
|
+
with open(vname, "w") as f:
|
|
53
|
+
f.write("%s\n"%("\n".join([json.dumps(v) for v in vz]),))
|
|
54
|
+
self.log("writing", aname)
|
|
55
|
+
soundfile.write(aname, result.audio, 24000)
|
|
56
|
+
|
|
57
|
+
VAGENT = None
|
|
58
|
+
kvox = Kvox()
|
|
59
|
+
kvoices = [
|
|
60
|
+
"af_heart", "af_bella", "af_nicole", "af_aoede", "af_kore", "af_sarah", "af_nova",
|
|
61
|
+
"af_sky", "af_alloy", "af_jessica", "af_river", "am_michael", "am_fenrir", "am_puck",
|
|
62
|
+
"am_echo", "am_eric", "am_liam", "am_onyx", "am_santa", "am_adam", "bf_emma",
|
|
63
|
+
"bf_isabella", "bf_alice", "bf_lily", "bm_george", "bm_fable", "bm_lewis", "bm_daniel"
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
def vagent():
|
|
67
|
+
global VAGENT
|
|
68
|
+
if not VAGENT:
|
|
69
|
+
from venvr import getagent
|
|
70
|
+
VAGENT = getagent("kovo", ["kokoro", "soundfile"])
|
|
71
|
+
VAGENT.register(Kvox)
|
|
72
|
+
return VAGENT
|
|
73
|
+
|
|
74
|
+
def vox(text, voice="af_heart", speed=1, lang_code='a', filename="tts", say=False):
|
|
75
|
+
if voice == "random":
|
|
76
|
+
voice = random.choice(kvoices)
|
|
77
|
+
try:
|
|
78
|
+
import kokoro
|
|
79
|
+
print("found kokoro")
|
|
80
|
+
kvox(text, voice, speed, lang_code, filename)
|
|
81
|
+
except:
|
|
82
|
+
print("no kokoro - using venvr")
|
|
83
|
+
vagent().run("Kvox", text, voice, speed, lang_code, filename)
|
|
84
|
+
say and cmd("mplayer %s.mp3"%(filename,))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .ander import android
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from fyg.util import log, ask, confirm, selnum
|
|
3
|
+
from cantools.util import cmd, output, mkdir, cp
|
|
4
|
+
from cantools.util.system import envget, envset
|
|
5
|
+
from cantools.util.admin import _which, javaver
|
|
6
|
+
from .data import TEMPLATES
|
|
7
|
+
|
|
8
|
+
class Android(object):
|
|
9
|
+
def __init__(self, url, name=None, package=None, auto=False):
|
|
10
|
+
self.setVars(url, name, package, auto)
|
|
11
|
+
self.setMode()
|
|
12
|
+
self.dirs()
|
|
13
|
+
self.files()
|
|
14
|
+
self.icons()
|
|
15
|
+
os.chdir(self.name)
|
|
16
|
+
self.apk()
|
|
17
|
+
self.install()
|
|
18
|
+
log("goodbye")
|
|
19
|
+
|
|
20
|
+
def setVars(self, url, name=None, package=None, auto=False):
|
|
21
|
+
if "://" not in url:
|
|
22
|
+
url = "https://%s"%(url,)
|
|
23
|
+
parts = url.split("://").pop().split("/").pop(0).split(".")
|
|
24
|
+
self.url = url
|
|
25
|
+
self.auto = auto
|
|
26
|
+
self.name = name or self.ask("name", parts[0])
|
|
27
|
+
parts.reverse()
|
|
28
|
+
self.package = package or self.ask("package name", ".".join(parts))
|
|
29
|
+
self.dir = self.package.replace(".", "/")
|
|
30
|
+
self.tmps = TEMPLATES["android"]
|
|
31
|
+
|
|
32
|
+
def ask(self, question, default=None):
|
|
33
|
+
if default and self.auto:
|
|
34
|
+
log("question '%s' -> choosing '%s'"%(question, default), important=True)
|
|
35
|
+
return default
|
|
36
|
+
return ask(question, default)
|
|
37
|
+
|
|
38
|
+
def conf(self, condition, default=False):
|
|
39
|
+
if self.auto:
|
|
40
|
+
log("confirmation '%s' -> deciding '%s'"%(condition, default), important=True)
|
|
41
|
+
return default
|
|
42
|
+
return confirm(condition, default)
|
|
43
|
+
|
|
44
|
+
def setMode(self, mode="debug"):
|
|
45
|
+
self.mode = mode
|
|
46
|
+
self.debug = mode == "debug"
|
|
47
|
+
|
|
48
|
+
def dirs(self):
|
|
49
|
+
if not self.conf("assemble directory hierarchy", True): return
|
|
50
|
+
mkdir("%s/src/main/java/%s"%(self.name, self.dir), True)
|
|
51
|
+
mkdir("%s/src/main/res"%(self.name,))
|
|
52
|
+
|
|
53
|
+
def files(self):
|
|
54
|
+
if not self.conf("create project files", True): return
|
|
55
|
+
self.jv = javaver()
|
|
56
|
+
cp(self.tmps["manifest"]%(self.name, self.package, self.name),
|
|
57
|
+
"%s/src/main/AndroidManifest.xml"%(self.name))
|
|
58
|
+
cp(self.tmps["activity"]%(self.package, self.url),
|
|
59
|
+
"%s/src/main/java/%s/MainActivity.java"%(self.name, self.dir))
|
|
60
|
+
cp(self.tmps["gradle"]%(self.package, self.jv, self.jv),
|
|
61
|
+
"%s/build.gradle"%(self.name,))
|
|
62
|
+
cp(self.tmps["properties"], "%s/gradle.properties"%(self.name,))
|
|
63
|
+
|
|
64
|
+
def icons(self):
|
|
65
|
+
if not self.conf("generate icons", True): return
|
|
66
|
+
ipath = self.ask("image path", "icon.png")
|
|
67
|
+
for k, v in self.tmps["isizes"].items():
|
|
68
|
+
wpath = "%s/src/main/res/drawable-%s"%(self.name, k)
|
|
69
|
+
mkdir(wpath)
|
|
70
|
+
cmd(self.tmps["icons"]%(ipath, v, wpath))
|
|
71
|
+
|
|
72
|
+
def chenv(self):
|
|
73
|
+
for name, cfg in self.tmps["env"].items():
|
|
74
|
+
if not envget(name):
|
|
75
|
+
log("%s not set!"%(name,))
|
|
76
|
+
envset(name, self.ask("%s location"%(name,),
|
|
77
|
+
output("locate %s"%(cfg["locater"].replace("_JV_",
|
|
78
|
+
self.jv),)).split(cfg["splitter"]).pop(0)))
|
|
79
|
+
|
|
80
|
+
def apk(self):
|
|
81
|
+
if not self.conf("build apk", True): return
|
|
82
|
+
self.chenv()
|
|
83
|
+
self.setMode(selnum(["debug", "release"]))
|
|
84
|
+
gcmd = self.debug and "assembleDebug" or "assemble"
|
|
85
|
+
if self.conf("add stacktrace flag"):
|
|
86
|
+
gcmd = "%s --stacktrace"%(gcmd,)
|
|
87
|
+
if self.conf("specify trustStore cacerts", True):
|
|
88
|
+
tsca = selnum(output("locate cacerts | grep java").split("\n"))
|
|
89
|
+
tspw = self.ask("trustStore password", "changeit")
|
|
90
|
+
gcmd = self.tmps["tstore"]%(gcmd, tsca, tspw)
|
|
91
|
+
cmd("gradle %s"%(gcmd,))
|
|
92
|
+
|
|
93
|
+
def install(self):
|
|
94
|
+
if not self.conf("install on device", True): return
|
|
95
|
+
aname = self.debug and "%s-debug"%(self.name,) or self.name
|
|
96
|
+
cmd("adb install build/outputs/apk/%s/%s.apk"%(self.mode, aname))
|
|
97
|
+
|
|
98
|
+
def android(url=None, auto=False):
|
|
99
|
+
if not _which("java", "gradle", "adb", "convert"):
|
|
100
|
+
return log("build aborted!")
|
|
101
|
+
Android(url or ask("url", "http://ct.mkult.co"), auto=auto)
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# reference:
|
|
2
|
+
# - https://github.com/raelmax/android-webview
|
|
3
|
+
# - https://czak.pl/posts/minimal-android-project
|
|
4
|
+
|
|
5
|
+
AMAN = """<?xml version="1.0" encoding="utf-8"?>
|
|
6
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
7
|
+
android:versionCode="1"
|
|
8
|
+
android:versionName="1.0" >
|
|
9
|
+
|
|
10
|
+
<uses-sdk />
|
|
11
|
+
|
|
12
|
+
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
|
13
|
+
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
|
14
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
15
|
+
<uses-permission android:name="android.permission.CAMERA" />
|
|
16
|
+
|
|
17
|
+
<application
|
|
18
|
+
android:allowBackup="true"
|
|
19
|
+
android:icon="@drawable/ic_launcher"
|
|
20
|
+
android:label="%s"
|
|
21
|
+
android:theme="@android:style/Theme.NoTitleBar" >
|
|
22
|
+
<activity
|
|
23
|
+
android:name="%s.MainActivity"
|
|
24
|
+
android:configChanges="orientation|screenSize"
|
|
25
|
+
android:label="%s"
|
|
26
|
+
android:exported="true" >
|
|
27
|
+
<intent-filter>
|
|
28
|
+
<action android:name="android.intent.action.MAIN" />
|
|
29
|
+
<category android:name="android.intent.category.LAUNCHER" />
|
|
30
|
+
</intent-filter>
|
|
31
|
+
</activity>
|
|
32
|
+
</application>
|
|
33
|
+
</manifest>
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
AMAC = """package %s;
|
|
37
|
+
import android.Manifest;
|
|
38
|
+
import android.app.Activity;
|
|
39
|
+
import android.os.Bundle;
|
|
40
|
+
import android.view.KeyEvent;
|
|
41
|
+
import android.view.Window;
|
|
42
|
+
import android.webkit.WebView;
|
|
43
|
+
import android.webkit.WebViewClient;
|
|
44
|
+
import android.webkit.WebChromeClient;
|
|
45
|
+
import android.webkit.PermissionRequest;
|
|
46
|
+
import android.content.pm.PackageManager;
|
|
47
|
+
import androidx.core.content.ContextCompat;
|
|
48
|
+
|
|
49
|
+
public class MainActivity extends Activity {
|
|
50
|
+
private WebView mWebView;
|
|
51
|
+
|
|
52
|
+
@Override
|
|
53
|
+
public void onCreate(Bundle savedInstanceState) {
|
|
54
|
+
super.onCreate(savedInstanceState);
|
|
55
|
+
MainActivity thaz = this;
|
|
56
|
+
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
|
57
|
+
mWebView = new WebView(this);
|
|
58
|
+
mWebView.getSettings().setMediaPlaybackRequiresUserGesture(false);
|
|
59
|
+
mWebView.getSettings().setJavaScriptEnabled(true);
|
|
60
|
+
mWebView.getSettings().setDomStorageEnabled(true);
|
|
61
|
+
mWebView.getSettings().setUseWideViewPort(true);
|
|
62
|
+
mWebView.loadUrl("%s");
|
|
63
|
+
mWebView.setWebViewClient(new WebViewClient() {
|
|
64
|
+
@Override
|
|
65
|
+
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
|
66
|
+
view.loadUrl(url);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
mWebView.setWebChromeClient(new WebChromeClient(){
|
|
71
|
+
// Need to accept permissions to use the camera
|
|
72
|
+
@Override
|
|
73
|
+
public void onPermissionRequest(final PermissionRequest request) {
|
|
74
|
+
// grants permission for app. video not showing
|
|
75
|
+
if (ContextCompat.checkSelfPermission(thaz, Manifest.permission.CAMERA)
|
|
76
|
+
!= PackageManager.PERMISSION_GRANTED
|
|
77
|
+
) {
|
|
78
|
+
requestPermissions(new String[]{Manifest.permission.CAMERA}, 1010);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (ContextCompat.checkSelfPermission(thaz, Manifest.permission.RECORD_AUDIO)
|
|
82
|
+
!= PackageManager.PERMISSION_GRANTED
|
|
83
|
+
) {
|
|
84
|
+
requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 1010);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
request.grant(request.getResources()); // is this right?
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
this.setContentView(mWebView);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@Override
|
|
94
|
+
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
|
|
95
|
+
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
|
|
96
|
+
mWebView.goBack();
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
return super.onKeyDown(keyCode, event);
|
|
100
|
+
}
|
|
101
|
+
}"""
|
|
102
|
+
|
|
103
|
+
ABG = """buildscript {
|
|
104
|
+
repositories {
|
|
105
|
+
google()
|
|
106
|
+
mavenCentral()
|
|
107
|
+
}
|
|
108
|
+
dependencies {
|
|
109
|
+
classpath 'com.android.tools.build:gradle:8.5.2'
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
repositories {
|
|
114
|
+
google()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
apply plugin: 'com.android.application'
|
|
118
|
+
|
|
119
|
+
dependencies {
|
|
120
|
+
implementation 'androidx.appcompat:appcompat:1.1.0'
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
android {
|
|
124
|
+
namespace = "%s"
|
|
125
|
+
|
|
126
|
+
compileSdkVersion 34
|
|
127
|
+
|
|
128
|
+
defaultConfig {
|
|
129
|
+
targetSdk = 34
|
|
130
|
+
minSdkVersion = 14
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
compileOptions {
|
|
134
|
+
sourceCompatibility JavaVersion.VERSION_%s
|
|
135
|
+
targetCompatibility JavaVersion.VERSION_%s
|
|
136
|
+
}
|
|
137
|
+
}"""
|
|
138
|
+
|
|
139
|
+
AGP = """android.useAndroidX=true
|
|
140
|
+
android.enableJetifier=true"""
|
|
141
|
+
|
|
142
|
+
TEMPLATES = {
|
|
143
|
+
"android": {
|
|
144
|
+
"manifest": AMAN,
|
|
145
|
+
"activity": AMAC,
|
|
146
|
+
"gradle": ABG,
|
|
147
|
+
"properties": AGP,
|
|
148
|
+
"icons": "convert -background none %s -resize %s %s/ic_launcher.png",
|
|
149
|
+
"tstore": "%s -Djavax.net.ssl.trustStore=%s -Djavax.net.ssl.trustStorePassword=%s",
|
|
150
|
+
"isizes": {
|
|
151
|
+
'ldpi': '36x36',
|
|
152
|
+
'mdpi': '48x48',
|
|
153
|
+
'hdpi': '72x72',
|
|
154
|
+
'xhdpi': '96x96'
|
|
155
|
+
},
|
|
156
|
+
"env": {
|
|
157
|
+
"JAVA_HOME": {
|
|
158
|
+
"locater": "cacerts|grep jvm/java-_JV_-",
|
|
159
|
+
"splitter": "/lib/security"
|
|
160
|
+
},
|
|
161
|
+
"ANDROID_HOME": {
|
|
162
|
+
"locater": "/lib/android-sdk",
|
|
163
|
+
"splitter": "\n"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
cantools/util/system.py
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import os, sys
|
|
2
|
-
|
|
3
|
-
from commands import getoutput # py2
|
|
4
|
-
except:
|
|
5
|
-
from subprocess import getoutput # py3
|
|
6
|
-
from fyg.util import log, read, write, rm
|
|
1
|
+
import os, sys
|
|
2
|
+
from fyg.util import log, read, write, rm, sudoed, cmd, output
|
|
7
3
|
|
|
8
4
|
def cp(content, fname): # more write than copy, buuuut...
|
|
9
5
|
log("writing %s"%(fname,), 2)
|
|
@@ -40,23 +36,6 @@ def mkdir(pname, recursive=False):
|
|
|
40
36
|
def sed(fname, flag, replacement, target=None):
|
|
41
37
|
write(read(fname).replace(flag, replacement), target or fname)
|
|
42
38
|
|
|
43
|
-
def sudoed(cline, sudo=False):
|
|
44
|
-
if sudo and platform.system() != "Windows" and os.geteuid(): # !root
|
|
45
|
-
cline = "sudo %s"%(cline,)
|
|
46
|
-
return cline
|
|
47
|
-
|
|
48
|
-
def cmd(cline, sudo=False, silent=False):
|
|
49
|
-
cline = sudoed(cline, sudo)
|
|
50
|
-
silent or log('issuing command: "%s"'%(cline,), 2)
|
|
51
|
-
subprocess.call(cline, shell=True)
|
|
52
|
-
|
|
53
|
-
def output(cline, sudo=False, silent=False, loud=False):
|
|
54
|
-
cline = sudoed(cline, sudo)
|
|
55
|
-
silent or log('getting output for: "%s"'%(cline,), 2)
|
|
56
|
-
output = getoutput(cline)
|
|
57
|
-
loud and log(output)
|
|
58
|
-
return output
|
|
59
|
-
|
|
60
39
|
def envget(name):
|
|
61
40
|
return output("echo $%s"%(name,))
|
|
62
41
|
|
cantools/web/__init__.py
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
from
|
|
1
|
+
from cantools import config
|
|
2
2
|
|
|
3
3
|
if config.web.server == "gae":
|
|
4
4
|
from .gae_server import *
|
|
5
5
|
elif config.web.server == "dez":
|
|
6
|
-
from
|
|
6
|
+
from .bw import *
|
|
7
|
+
from babyweb import *
|
|
8
|
+
from babyweb import mail
|
|
9
|
+
from babyweb.sms import send_sms
|
|
10
|
+
from babyweb.mail import send_mail, email_admins, email_reportees, mailer, reader, check_inbox, scanner, on_mail
|
|
7
11
|
else:
|
|
8
12
|
from cantools import util
|
|
9
13
|
util.error("no web server specified")
|
cantools/web/bw.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import json, gc, os, inspect, threading, psutil
|
|
2
|
+
from babyweb.daemons import WebBase, initWebs, logger_getter
|
|
3
|
+
from babyweb.server import run_dez_webserver
|
|
4
|
+
from babyweb.config import config as babyfyg
|
|
5
|
+
from babyweb.logger import log, syslog
|
|
6
|
+
from ..util import init_rel
|
|
7
|
+
from cantools import config
|
|
8
|
+
|
|
9
|
+
A_STATIC = {
|
|
10
|
+
"dynamic": { "/": "_/dynamic", "/css/": "_/css", "/js/CT/": "js/CT", "/logs/": "logs", "/logs": "logs" },
|
|
11
|
+
"static": { "/": "_/static", "/css/": "_/css", "/js/CT/": "js/CT", "/logs/": "logs", "/logs": "logs" },
|
|
12
|
+
"production": { "/": "_/production", "/css/": "_/css", "/logs/": "logs", "/logs": "logs" },
|
|
13
|
+
}
|
|
14
|
+
A_CB = { "/admin": "admin", "/_db": "_db" }
|
|
15
|
+
|
|
16
|
+
def setcfg():
|
|
17
|
+
syslog("passing configuration to babyweb")
|
|
18
|
+
for prop in ["cache", "encode", "mempad", "web", "cron", "scrambler"]:
|
|
19
|
+
babyfyg.update(prop, config[prop])
|
|
20
|
+
for prop in ["contacts", "reportees"]:
|
|
21
|
+
babyfyg.admin.update(prop, config.admin[prop])
|
|
22
|
+
for prop in ["verify", "certfile", "keyfile", "cacerts"]:
|
|
23
|
+
babyfyg.ssl.update(prop, config.ssl[prop])
|
|
24
|
+
for prop in ["oflist", "openfiles", "tracemalloc", "allow"]:
|
|
25
|
+
babyfyg.log.update(prop, config.log[prop])
|
|
26
|
+
for prop in ["active", "user", "gateway", "minport", "maxport"]:
|
|
27
|
+
babyfyg.proxy.update(prop, config.proxy[prop])
|
|
28
|
+
babyfyg.update("memcache", config.memcache.request)
|
|
29
|
+
bmfg = babyfyg.mail
|
|
30
|
+
bmfg.update("mailer", config.mailer)
|
|
31
|
+
bmfg.update("gmailer", config.gmailer)
|
|
32
|
+
bmfg.update("name", config.mailername)
|
|
33
|
+
bmfg.update("html", config.mailhtml)
|
|
34
|
+
bmfg.update("verbose", config.mailoud)
|
|
35
|
+
bmfg.update("scantick", config.mailscantick)
|
|
36
|
+
|
|
37
|
+
setcfg()
|
|
38
|
+
|
|
39
|
+
class Admin(WebBase):
|
|
40
|
+
def __init__(self, bind_address, port, logger_getter, shield, mempad):
|
|
41
|
+
self.logger = logger_getter("Admin")
|
|
42
|
+
acfg = config.admin
|
|
43
|
+
WebBase.__init__(self, bind_address, port, logger_getter, # share shield/blacklist
|
|
44
|
+
A_STATIC[config.mode], A_CB, acfg.whitelist, config.web.blacklist, shield, mempad)
|
|
45
|
+
self.add_cb_rule("/_report", self.report)
|
|
46
|
+
|
|
47
|
+
def report(self, req):
|
|
48
|
+
report = json.dumps({
|
|
49
|
+
"threads": threading.active_count(),
|
|
50
|
+
"stack_frames": len(inspect.stack()),
|
|
51
|
+
"web": self.controller.webs["web"].daemon.counter.report(),
|
|
52
|
+
"admin": self.daemon.counter.report(),
|
|
53
|
+
"gc": len(gc.get_objects()),
|
|
54
|
+
"mem": psutil.Process(os.getpid()).memory_percent()
|
|
55
|
+
})
|
|
56
|
+
self.logger.info(report)
|
|
57
|
+
self.daemon.respond(req, report)
|
|
58
|
+
|
|
59
|
+
def run_bw():
|
|
60
|
+
syslog("initializing web server")
|
|
61
|
+
init_rel()
|
|
62
|
+
initWebs({
|
|
63
|
+
"admin": {
|
|
64
|
+
"daemon": Admin,
|
|
65
|
+
"config": config.admin
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
config.admin.update("pw",
|
|
69
|
+
config.cache("admin password? ", overwrite=config.newpass))
|
|
70
|
+
run_dez_webserver()
|
cantools/web/gae_server.py
CHANGED