first commit

This commit is contained in:
yumoqing 2025-07-16 15:07:06 +08:00
commit f3d40b143c
139 changed files with 114745 additions and 0 deletions

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# iptv
iptv ui

90
app/downloadchannels.py Normal file
View File

@ -0,0 +1,90 @@
# url=https://m3uplaylist.download/free-iptv-m3u-playlists
# the m3u playlist from here
import sys
import os
import asyncio
from datetime import datetime
from appPublic.jsonConfig import getConfig
from appPublic.httpclient import HttpClient
from appPublic.uniqueID import getID
from appPublic.log import debug
from sqlor.dbpools import DBPools
import m3u
async def download(url):
client = HttpClient()
txt = await client.request(url, 'GET')
clist = m3u.m3uParser(txt)
return clist
async def saveChannels(media_type,clist, dbname):
pool = DBPools()
sql = """insert into iptvchannels
(
id,
tv_group,
tv_name,
logo_url,
url,
media_type,
download_date,
del_flg
)
values
(
${id}$,
${tv_group}$,
${tv_name}$,
${logo_url}$,
${url}$,
${media_type}$,
${download_date}$,
'0'
)"""
dup = 0
query = """select * from iptvchannels where url=${url}$"""
async with pool.sqlorContext(dbname) as sor:
for r in clist:
q = await sor.sqlExe(query,r)
if len(q) < 1:
r['media_type'] = media_type
r['id'] = getID()
r['tv_group'] = r.get('group-title','')[:500]
r['tv_name'] = r.get('name','')[:500]
r['logo_url'] = r.get('tvg-logo',None)
if r['logo_url'] and len(r['logo_url']) > 1000:
r['logo_url'] = None
if len(r['url']) >= 1000:
continue;
dt = datetime.now()
r['download_date'] = '%d-%02d-%02d' % (dt.year,dt.month,dt.day)
await sor.sqlExe(sql,r)
else:
dup += 1
debug(f'{dup} exists')
async def load_url_iptv(media_type,url, dbname):
clist = await download(url)
if clist:
debug('%d channels' % len(clist))
await saveChannels(media_type,clist, dbname)
else:
debug(f'{url} return None')
if __name__ == '__main__':
import sys
if len(sys.argv) < 3:
print('Usage:\n%s workdir m3u_playlist_url\n' % sys.argv[0])
sys.exit(1)
p = sys.argv[1]
config = getConfig(p, {'workdir':p})
DBPools(config.databases)
dbname = 'iptvdb'
media_type = 'iptv'
if len(sys.argv) > 3:
media_type = sys.argv[3]
loop = asyncio.get_event_loop()
loop.run_until_complete(load_url_iptv(media_type, sys.argv[2], dbname))

29
app/iptv.py Normal file
View File

@ -0,0 +1,29 @@
import json
import os
from appPublic.worker import awaitify
from appPublic.jsonConfig import getConfig
from ahserver.serverenv import ServerEnv
from sqlor.dbpools import DBPools
from ahserver.webapp import webapp
from downloadchannels import load_url_iptv
from time import time
async def get_channel_by_id(id):
db = DBPools()
async with db.sqlorContext('iptvdb') as sor:
sql = "select * from iptvchannels where id=${id}$"
recs = await sor.sqlExe(sql, {'id':id})
if len(recs) < 1:
return None
return recs[0]
return None
def init_func():
g = ServerEnv()
g.load_url_iptv = load_url_iptv
g.get_channel_by_id = get_channel_by_id
if __name__ == '__main__':
webapp(init_func)

87
app/m3u.py Normal file
View File

@ -0,0 +1,87 @@
import codecs
def tvgParser(txt):
d = {}
buf = ''
k = ''
inbrace = False
for c in txt:
if c == '"':
if inbrace:
inbrace = False
d[k] = buf
buf = ''
k = ''
else:
inbrace = True
continue
if c == '=':
k = buf
buf = ''
continue
if c == ' ':
if inbrace:
buf = '%s%s' % (buf,c)
continue
buf = '%s%s' % (buf,c)
if k != '':
v = buf
d[k] = v
return d
def channelInfo(l):
g = {}
e = l.split(',')
info = e[-2]
fo=info.split(' ',1)
if len(fo) == 2:
_,tvginfo=info.split(' ',1)
g = tvgParser(tvginfo)
g['name'] = e[-1]
return g
def name_url_m3u(text):
ret = []
for i, line in enumerate(text.split('\n')):
llist = line.split(',')
if len(llist) != 2:
return ret
ret.append({'url':llist[1], 'name':llist[0]})
return ret
def m3uParser(text):
text = ''.join(text.split('\r'))
newchannel = False
channels = []
for i,line in enumerate(text.split('\n')):
if i==0 and not line.startswith('#EXTM3U'):
return name_url_m3u(text)
if i == 0:
continue
if line == '':
continue
if line.startswith('#EXTINF'):
channel = channelInfo(line)
status = 'url'
continue
if line.startswith('http://') or line.startswith('https://'):
channel['url'] = line
channels.append(channel)
continue
return channels
def testfile(filename):
with codecs.open(filename,'r','utf-8') as f:
text = f.read()
m3uParser(text)
if __name__ == '__main__':
import sys
testfile(sys.argv[1])

61
channelcheck.py Normal file
View File

@ -0,0 +1,61 @@
import time
import asyncio
from sqlor.dbpools import DBPools
from appPublic.worker import AsyncWorker
from appPublic.httpclient import HttpClient
dbs = {
"iptvdb":{
"driver":"aiomysql",
"async_mode":True,
"coding":"utf8",
"dbname":"iptvdb",
"maxconn":100,
"kwargs":{
"user":"test",
"db":"iptvdb",
"password":"QUZVcXg5V1p1STMybG5Ia6mX9D0v7+g=",
"host":"localhost"
}
}
}
async def check_availble(rec):
url = rec['url']
print(f'handle {rec["id"]}, {url}...')
t =time.time()
r = None
try:
hc = HttpClient()
r = await hc.get(url)
await hc.close()
except:
pass
if r is None:
db = DBPools()
d = {
"id":rec['id']
}
print('sql run ... ', d)
async with db.sqlorContext('iptvdb') as sor:
await sor.sqlExe("update iptvchannels set del_flg='1' where id=${id}$", d)
t1 = time.time()
print(f'{rec["id"]} deleted cost {t1 - t} seconds')
return
t1 = time.time()
print(f'{url} ok {t1 - t} seconds')
async def main():
db = DBPools(dbs)
sql = "select * from iptvchannels where del_flg='0'"
recs = []
async with db.sqlorContext('iptvdb') as sor:
recs = await sor.sqlExe(sql, {})
aw = AsyncWorker(maxtask=10)
g = [asyncio.create_task(aw(check_availble, r)) for r in recs ]
await asyncio.wait(g)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())

1
client/README.md Executable file
View File

@ -0,0 +1 @@
"# doodah"

7
client/android/build.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
VERSION=$(echo "echo $(grep -e "[\'\"].*[\'\"]" -o version.py)" | sh)
rm ./bin/*
buildozer android clean
buildozer android release
apksigning.sh ./bin/doodah-${VERSION}-armeabi-v7a-release-unsigned.apk ${HOME}/apks/doodah_${VERSION}.apk "ymq_kivyapp"

372
client/buildozer.spec Executable file
View File

@ -0,0 +1,372 @@
[app]
# (str) Title of your application
title = Doodah
# (str) Package name
package.name = doodah
# (str) Package domain (needed for android/ios packaging)
package.domain = com.bsppo
# (str) Source code where the main.py live
source.dir = .
# (list) Source files to include (let empty to include all the files)
source.include_exts = json, py,png,jpg,kv,atlas,ttf
# (list) List of inclusions using pattern matching
#source.include_patterns = assets/*,images/*.png
source.include_patterns = imgs/*.png, conf/*.json, \
kivyblocks/imgs/*.png, \
kivyblocks/ttf/*.ttf, \
kivyblocks/image_processing/cascades/*.xml, \
kivyblocks/xcamera/data/*, \
kivyblocks/xcamera/xcamera.kv, \
plugins/*, \
plugins/pub/*.py
# (list) Source files to exclude (let empty to not exclude anything)
source.exclude_exts = spec
# (list) List of directory to exclude (let empty to not exclude anything)
source.exclude_dirs = tests, bin, dist, build, __pycache__
# (list) List of exclusions using pattern matching
#source.exclude_patterns = license,images/*/*.jpg
# (str) Application versioning (method 1)
# version = 0.1
# (str) Application versioning (method 2)
version.regex = __version__ = ['"](.*)['"]
version.filename = %(source.dir)s/version.py
# (list) Application requirements
# comma separated e.g. requirements = sqlite3,kivy
requirements = multidict, async-timeout, attrs, typing-extensions, yarl, aiohttp, asyncio, plyer, numpy, \
openssl, ffpyplayer, ffpyplayer_codecs, libx264, cryptography, pillow, qrcode, ffmpeg, pygments, \
markupsafe,jinja2,urllib3, chardet, idna, requests,python3,kivy,python-osc, \
regex, opencv, bs4, beautifulsoup4, soupsieve, lxml, portaudio, pyaudio, ujson, \
git+https://github.com/yumoqing/appPublic, \
git+https://github.com/yumoqing/kivycalendar, \
git+https://github.com/yumoqing/kivy-blocks
# (str) Custom source folders for requirements
# Sets custom source for any requirements with recipes
# requirements.source.appPublic = /home/ymq/pydev/github/appPublic
# requirements.source.kivycalendar = /home/ymq/pydev/github/kivycalendar
# requirements.source.kivyblocks = /home/ymq/pydev/github/kivy-blocks
requirements.source.ffmpeg = /home/ymq/p4a/packages/ffmpeg
requirements.source.kivy = /home/ymq/p4a/packages/kivy
requirements.source.pillow = /home/ymq/p4a/packages/Pillow
requirements.source.cffi = /home/ymq/p4a/packages/cffi
requirements.source.cryptography = /home/ymq/p4a/packages/cryptography
requirements.source.cython = /home/ymq/p4a/packages/cython
requirements.source.ffpyplayer = /home/ymq/p4a/packages/ffpyplayer
requirements.source.freetype = /home/ymq/p4a/packages/freetype
requirements.source.jpeg = /home/ymq/p4a/packages/jpeg
requirements.source.hostpython3 = /home/ymq/p4a/packages/Python-3.8.1
requirements.source.libffi = /home/ymq/p4a/packages/libffi
requirements.source.libx264 = /home/ymq/p4a/packages/libx264
requirements.source.numpy = /home/ymq/p4a/packages/numpy
requirements.source.openssl = /home/ymq/p4a/packages/openssl
requirements.source.png = /home/ymq/p4a/packages/png
requirements.source.pycparser = /home/ymq/p4a/packages/pycparser
requirements.source.pyjnius = /home/ymq/p4a/packages/pyjnius
requirements.source.python3 = /home/ymq/p4a/packages/python3
# requirements.source.libshine = /home/ymq/p4a/packages/libshine
# requirements.source.sdl2 = /home/ymq/p4a/packages/sdl2
# requirements.source.sdl2_image = /home/ymq/p4a/packages/sdl2_image
# requirements.source.sdl2_mixer = /home/ymq/p4a/packages/sdl2_mixer
# requirements.source.sdl2_ttf = /home/ymq/p4a/packages/sdl2_ttf
requirements.source.setuptools = /home/ymq/p4a/packages/setuptools
requirements.source.six = /home/ymq/p4a/packages/six
requirements.source.sqlite3 = /home/ymq/p4a/packages/sqlite3
# (list) Garden requirements
#garden_requirements =
# (str) Presplash of the application
presplash.filename = %(source.dir)s/doodah.png
# (str) Icon of the application
icon.filename = %(source.dir)s/doodah.png
# (str) Supported orientation (one of landscape, sensorLandscape, portrait or all)
orientation = all
# (list) List of service to declare
#services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
#
# OSX Specific
#
#
# author = © Copyright Info
# change the major version of python used by the app
# osx.python_version = 3
# Kivy version to use
# osx.kivy_version = 1.9.1
#
# Android specific
#
# (bool) Indicate if the application should be fullscreen or not
fullscreen = True
# (string) Presplash background color (for new android toolchain)
# Supported formats are: #RRGGBB #AARRGGBB or one of the following names:
# red, blue, green, black, white, gray, cyan, magenta, yellow, lightgray,
# darkgray, grey, lightgrey, darkgrey, aqua, fuchsia, lime, maroon, navy,
# olive, purple, silver, teal.
#android.presplash_color = #FFFFFF
# (list) Permissions
#android.permissions = INTERNET
android.permissions = INTERNET, CAMERA, VIBRATE, CALL_PHONE, CALL_PRIVILEGED
# (int) Target Android API, should be as high as possible.
# android.api = 23
# (int) Minimum API your APK will support.
# android.minapi = 21
# (int) Android SDK version to use
#android.sdk = 20
# (str) Android NDK version to use
#android.ndk = 19b
# (int) Android NDK API to use. This is the minimum API your app will support, it should usually match android.minapi.
# android.ndk_api = 21
# (bool) Use --private data storage (True) or --dir public storage (False)
#android.private_storage = True
# (str) Android NDK directory (if empty, it will be automatically downloaded.)
#android.ndk_path =
# (str) Android SDK directory (if empty, it will be automatically downloaded.)
#android.sdk_path =
# (str) ANT directory (if empty, it will be automatically downloaded.)
#android.ant_path =
# (bool) If True, then skip trying to update the Android sdk
# This can be useful to avoid excess Internet downloads or save time
# when an update is due and you just want to test/build your package
# android.skip_update = False
# (bool) If True, then automatically accept SDK license
# agreements. This is intended for automation only. If set to False,
# the default, you will be shown the license when first running
# buildozer.
# android.accept_sdk_license = False
# (str) Android entry point, default is ok for Kivy-based app
#android.entrypoint = org.renpy.android.PythonActivity
# (str) Android app theme, default is ok for Kivy-based app
# android.apptheme = "@android:style/Theme.NoTitleBar"
# (list) Pattern to whitelist for the whole project
#android.whitelist =
# (str) Path to a custom whitelist file
#android.whitelist_src =
# (str) Path to a custom blacklist file
#android.blacklist_src =
# (list) List of Java .jar files to add to the libs so that pyjnius can access
# their classes. Don't add jars that you do not need, since extra jars can slow
# down the build process. Allows wildcards matching, for example:
# OUYA-ODK/libs/*.jar
#android.add_jars = foo.jar,bar.jar,path/to/more/*.jar
# (list) List of Java files to add to the android project (can be java or a
# directory containing the files)
#android.add_src =
# (list) Android AAR archives to add (currently works only with sdl2_gradle
# bootstrap)
#android.add_aars =
# (list) Gradle dependencies to add (currently works only with sdl2_gradle
# bootstrap)
#android.gradle_dependencies =
# (list) add java compile options
# this can for example be necessary when importing certain java libraries using the 'android.gradle_dependencies' option
# see https://developer.android.com/studio/write/java8-support for further information
# android.add_compile_options = "sourceCompatibility = 1.8", "targetCompatibility = 1.8"
# (list) Gradle repositories to add {can be necessary for some android.gradle_dependencies}
# please enclose in double quotes
# e.g. android.gradle_repositories = "maven { url 'https://kotlin.bintray.com/ktor' }"
#android.add_gradle_repositories =
# (list) packaging options to add
# see https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html
# can be necessary to solve conflicts in gradle_dependencies
# please enclose in double quotes
# e.g. android.add_packaging_options = "exclude 'META-INF/common.kotlin_module'", "exclude 'META-INF/*.kotlin_module'"
#android.add_gradle_repositories =
# (list) Java classes to add as activities to the manifest.
#android.add_activities = com.example.ExampleActivity
# (str) OUYA Console category. Should be one of GAME or APP
# If you leave this blank, OUYA support will not be enabled
#android.ouya.category = GAME
# (str) Filename of OUYA Console icon. It must be a 732x412 png image.
#android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png
# (str) XML file to include as an intent filters in <activity> tag
#android.manifest.intent_filters =
# (str) launchMode to set for the main activity
#android.manifest.launch_mode = standard
# (list) Android additional libraries to copy into libs/armeabi
#android.add_libs_armeabi = libs/android/*.so
#android.add_libs_armeabi_v7a = libs/android-v7/*.so
#android.add_libs_arm64_v8a = libs/android-v8/*.so
#android.add_libs_x86 = libs/android-x86/*.so
#android.add_libs_mips = libs/android-mips/*.so
# (bool) Indicate whether the screen should stay on
# Don't forget to add the WAKE_LOCK permission if you set this to True
#android.wakelock = False
# (list) Android application meta-data to set (key=value format)
#android.meta_data =
# (list) Android library project to add (will be added in the
# project.properties automatically.)
#android.library_references =
# (list) Android shared libraries which will be added to AndroidManifest.xml using <uses-library> tag
#android.uses_library =
# (str) Android logcat filters to use
#android.logcat_filters = *:S python:D
# (bool) Copy library instead of making a libpymodules.so
#android.copy_libs = 1
# (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64
android.arch = armeabi-v7a
# (int) overrides automatic versionCode computation (used in build.gradle)
# this is not the same as app version and should only be edited if you know what you're doing
# android.numeric_version = 1
#
# Python for android (p4a) specific
#
# (str) python-for-android fork to use, defaults to upstream (kivy)
#p4a.fork = kivy
# (str) python-for-android branch to use, defaults to master
#p4a.branch = master
# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
p4a.source_dir = /home/ymq/p4a/python-for-android
# (str) The directory in which python-for-android should look for your own build recipes (if any)
#p4a.local_recipes =
# (str) Filename to the hook for p4a
#p4a.hook =
# (str) Bootstrap to use for android builds
# p4a.bootstrap = sdl2
# (int) port number to specify an explicit --port= p4a argument (eg for bootstrap flask)
#p4a.port =
#
# iOS specific
#
# (str) Path to a custom kivy-ios folder
#ios.kivy_ios_dir = ../kivy-ios
# Alternately, specify the URL and branch of a git checkout:
ios.kivy_ios_url = https://github.com/kivy/kivy-ios
ios.kivy_ios_branch = master
# Another platform dependency: ios-deploy
# Uncomment to use a custom checkout
#ios.ios_deploy_dir = ../ios_deploy
# Or specify URL and branch
ios.ios_deploy_url = https://github.com/phonegap/ios-deploy
ios.ios_deploy_branch = 1.7.0
# (str) Name of the certificate to use for signing the debug version
# Get a list of available identities: buildozer ios list_identities
#ios.codesign.debug = "iPhone Developer: <lastname> <firstname> (<hexstring>)"
# (str) Name of the certificate to use for signing the release version
#ios.codesign.release = %(ios.codesign.debug)s
[buildozer]
# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
log_level = 2
# (int) Display warning if buildozer is run as root (0 = False, 1 = True)
warn_on_root = 1
# (str) Path to build artifact storage, absolute or relative to spec file
# build_dir = ./.buildozer
# (str) Path to build output (i.e. .apk, .ipa) storage
# bin_dir = ./bin
# -----------------------------------------------------------------------------
# List as sections
#
# You can define all the "list" as [section:key].
# Each line will be considered as a option to the list.
# Let's take [app] / source.exclude_patterns.
# Instead of doing:
#
#[app]
#source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
#
# This can be translated into:
#
#[app:source.exclude_patterns]
#license
#data/audio/*.wav
#data/images/original/*
#
# -----------------------------------------------------------------------------
# Profiles
#
# You can extend section / key with a profile
# For example, you want to deploy a demo version of your application without
# HD content. You could first change the title to add "(demo)" in the name
# and extend the excluded directories to remove the HD content.
#
#[app@demo]
#title = My Application (demo)
#
#[app:source.exclude_patterns@demo]
#images/hd/*
#
# Then, invoke the command line with the "demo" profile:
#
#buildozer --profile demo android debug

24
client/conf/config.json Executable file
View File

@ -0,0 +1,24 @@
{
"font_sizes":{
"smallest":1.5,
"small":2,
"normal":2.5,
"large":3,
"huge":3.5,
"hugest":4
},
"css":{
"css_url":"/csses.json"
},
"color_style":"Grey",
"font_name":"normal",
"uihome":"http://localhost/iptv/n",
"i18n_url":"/public/i18n",
"root":{
"widgettype":"urlwidget",
"options":{
"url":"/index.ui"
}
}
}

BIN
client/doodah.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

19
client/loadplugins.py Executable file
View File

@ -0,0 +1,19 @@
import os
import sys
from appPublic.folderUtils import listFile
from appPublic.ExecFile import ExecFile
from kivy.logger import Logger
def load_plugins(p_dir):
ef = ExecFile()
pdir = os.path.join(p_dir, 'plugins')
if not os.path.isdir(pdir):
Logger.error('load_plugins:%s not exists', pdir)
return
sys.path.append(pdir)
for py in listFile(pdir, suffixs=['py'], rescursive=False):
ef.set('sys',sys)
ef.run(py)

1
client/macos/build.sh Normal file
View File

@ -0,0 +1 @@
pyinstaller -y --clean t_kboss.spec

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,244 @@
This file lists modules PyInstaller was not able to find. This does not
necessarily mean this module is required for running your program. Python and
Python 3rd-party packages include a lot of conditional or optional modules. For
example the module 'ntpath' only exists on Windows, whereas the module
'posixpath' only exists on Posix systems.
Types if import:
* top-level: imported at the top-level - look at these first
* conditional: imported within an if-statement
* delayed: imported within a function
* optional: imported within a try-except-statement
IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
tracking down the missing module yourself. Thanks!
missing module named pep517 - imported by importlib.metadata (delayed)
missing module named org - imported by copy (optional)
missing module named 'org.python' - imported by pickle (optional), xml.sax (delayed, conditional)
missing module named winreg - imported by importlib._bootstrap_external (conditional), mimetypes (optional), urllib.request (delayed, conditional, optional), requests.utils (delayed, conditional, optional), platform (delayed, optional), distutils.msvc9compiler (top-level), distutils._msvccompiler (top-level), pkg_resources._vendor.platformdirs.windows (delayed, optional), setuptools.msvc (conditional), setuptools._distutils._msvccompiler (top-level), setuptools._distutils.msvc9compiler (top-level), setuptools._distutils.msvccompiler (optional), pygments.formatters.img (optional)
missing module named nt - imported by os (delayed, conditional, optional), ntpath (optional), shutil (conditional), importlib._bootstrap_external (conditional), pathlib (conditional), ctypes (delayed, conditional)
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level)
missing module named _winapi - imported by encodings (delayed, conditional, optional), subprocess (optional), multiprocessing.connection (optional), multiprocessing.spawn (delayed, conditional), multiprocessing.reduction (conditional), multiprocessing.shared_memory (conditional), multiprocessing.heap (conditional), multiprocessing.popen_spawn_win32 (top-level), asyncio.windows_events (top-level), asyncio.windows_utils (top-level)
missing module named msvcrt - imported by subprocess (optional), getpass (optional), multiprocessing.spawn (delayed, conditional), multiprocessing.popen_spawn_win32 (top-level), asyncio.windows_events (top-level), asyncio.windows_utils (top-level), png (delayed, conditional)
missing module named vms_lib - imported by platform (delayed, optional)
missing module named 'java.lang' - imported by platform (delayed, optional), xml.sax._exceptions (conditional)
missing module named java - imported by platform (delayed)
missing module named _winreg - imported by platform (delayed, optional), pygments.formatters.img (optional)
missing module named win32con - imported by setuptools._distutils.msvccompiler (optional), kivy.core.window.window_sdl2 (delayed, conditional), kivy.core.window.window_pygame (delayed)
missing module named win32api - imported by setuptools._distutils.msvccompiler (optional), kivy.core.window.window_pygame (delayed)
missing module named 'distutils._log' - imported by setuptools._distutils.command.bdist_dumb (top-level), setuptools._distutils.command.bdist_rpm (top-level), setuptools._distutils.command.build_clib (top-level), setuptools._distutils.command.build_ext (top-level), setuptools._distutils.command.build_py (top-level), setuptools._distutils.command.build_scripts (top-level), setuptools._distutils.command.clean (top-level), setuptools._distutils.command.config (top-level), setuptools._distutils.command.install (top-level), setuptools._distutils.command.install_scripts (top-level), setuptools._distutils.command.register (top-level), setuptools._distutils.command.sdist (top-level)
missing module named usercustomize - imported by site (delayed, optional)
missing module named sitecustomize - imported by site (delayed, optional)
missing module named pygments.formatters.BBCodeFormatter - imported by pygments.formatters (top-level), kivy.uix.codeinput (top-level)
missing module named _manylinux - imported by packaging._manylinux (delayed, optional), setuptools._vendor.packaging._manylinux (delayed, optional), pkg_resources._vendor.packaging._manylinux (delayed, optional)
missing module named jnius - imported by kivy.metrics (delayed, conditional), kivy.app (delayed, conditional), kivyblocks.widgetExt.phonebutton (top-level), kivyblocks.widgetExt.androidwebview (top-level), kivyblocks.pyinterpreter (conditional), kivyblocks.blocksapp (conditional), plyer.platforms.android (top-level), pkg_resources._vendor.platformdirs.android (delayed, optional), kivy.core.clipboard.clipboard_android (top-level), kivy.core.audio.audio_android (top-level), kivy.core.camera.camera_android (top-level)
missing module named platformdirs - imported by pkg_resources._vendor.platformdirs.__main__ (top-level)
missing module named 'pkg_resources.extern.importlib_resources' - imported by pkg_resources._vendor.jaraco.text (optional)
missing module named 'typing.io' - imported by importlib.resources (top-level)
missing module named 'pkg_resources.extern.more_itertools' - imported by pkg_resources._vendor.jaraco.functools (top-level)
missing module named pkg_resources.extern.packaging - imported by pkg_resources.extern (top-level), pkg_resources (top-level)
missing module named pkg_resources.extern.platformdirs - imported by pkg_resources.extern (top-level), pkg_resources (top-level)
missing module named 'pkg_resources.extern.jaraco' - imported by pkg_resources (top-level), pkg_resources._vendor.jaraco.text (top-level)
missing module named ctags - imported by pygments.formatters.html (optional)
missing module named pygments.lexers.PrologLexer - imported by pygments.lexers (top-level), pygments.lexers.cplint (top-level)
missing module named PIL._imagingagg - imported by PIL (delayed, conditional, optional), PIL.ImageDraw (delayed, conditional, optional)
missing module named olefile - imported by PIL.FpxImagePlugin (top-level), PIL.MicImagePlugin (top-level)
missing module named psutil._psutil_aix - imported by psutil (top-level), psutil._psaix (top-level)
missing module named psutil._psutil_sunos - imported by psutil (top-level), psutil._pssunos (top-level)
missing module named psutil._psutil_bsd - imported by psutil (top-level), psutil._psbsd (top-level)
missing module named _psutil_windows - imported by psutil._pswindows (top-level)
missing module named psutil._psutil_windows - imported by psutil (conditional, optional), psutil._pswindows (optional)
missing module named psutil._psutil_linux - imported by psutil (top-level), psutil._pslinux (top-level)
missing module named dummy_threading - imported by requests.cookies (optional), psutil._compat (optional)
missing module named _dummy_thread - imported by cffi.lock (conditional, optional), numpy.core.arrayprint (optional)
missing module named numpy.core.result_type - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.float_ - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.number - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.object_ - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
missing module named numpy.core.all - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
missing module named numpy.core.bool_ - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.inf - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.array2string - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.lib.imag - imported by numpy.lib (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.lib.real - imported by numpy.lib (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.lib.iscomplexobj - imported by numpy.lib (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.signbit - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.isscalar - imported by numpy.core (delayed), numpy.testing._private.utils (delayed), numpy.lib.polynomial (top-level)
missing module named win32pdh - imported by numpy.testing._private.utils (delayed, conditional)
missing module named numpy.core.isinf - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.errstate - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
missing module named numpy.core.isfinite - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
missing module named numpy.core.isnan - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
missing module named numpy.core.array - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.isnat - imported by numpy.core (top-level), numpy.testing._private.utils (top-level)
missing module named numpy.core.ndarray - imported by numpy.core (top-level), numpy.testing._private.utils (top-level), numpy.lib.utils (top-level)
missing module named numpy.core.array_repr - imported by numpy.core (top-level), numpy.testing._private.utils (top-level)
missing module named numpy.core.arange - imported by numpy.core (top-level), numpy.testing._private.utils (top-level), numpy.fft.helper (top-level)
missing module named numpy.core.empty - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (top-level), numpy.fft.helper (top-level)
missing module named numpy.core.float32 - imported by numpy.core (top-level), numpy.testing._private.utils (top-level)
missing module named numpy.core.intp - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (top-level)
missing module named _overlapped - imported by asyncio.windows_events (top-level)
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
missing module named numpy.core.linspace - imported by numpy.core (top-level), numpy.lib.index_tricks (top-level)
missing module named numpy.core.iinfo - imported by numpy.core (top-level), numpy.lib.twodim_base (top-level)
missing module named numpy.core.transpose - imported by numpy.core (top-level), numpy.lib.function_base (top-level)
missing module named numpy.core.asarray - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.lib.utils (top-level), numpy.fft._pocketfft (top-level), numpy.fft.helper (top-level)
missing module named numpy.core.integer - imported by numpy.core (top-level), numpy.fft.helper (top-level)
missing module named numpy.core.sqrt - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.fft._pocketfft (top-level)
missing module named numpy.core.conjugate - imported by numpy.core (top-level), numpy.fft._pocketfft (top-level)
missing module named numpy.core.swapaxes - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.fft._pocketfft (top-level)
missing module named numpy.core.zeros - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.fft._pocketfft (top-level)
missing module named numpy.core.reciprocal - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.sort - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.argsort - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.sign - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.count_nonzero - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.divide - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.matmul - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.asanyarray - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.atleast_2d - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.product - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.amax - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.amin - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.moveaxis - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.geterrobj - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.finfo - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.sum - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.multiply - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.add - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.dot - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.Inf - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.newaxis - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.complexfloating - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.inexact - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.cdouble - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.csingle - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.double - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.single - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.intc - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.empty_like - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named threadpoolctl - imported by numpy.lib.utils (delayed, optional)
missing module named numpy.core.ufunc - imported by numpy.core (top-level), numpy.lib.utils (top-level)
missing module named numpy.core.ones - imported by numpy.core (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.hstack - imported by numpy.core (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.atleast_1d - imported by numpy.core (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.atleast_3d - imported by numpy.core (top-level), numpy.lib.shape_base (top-level)
missing module named numpy.core.vstack - imported by numpy.core (top-level), numpy.lib.shape_base (top-level)
missing module named pickle5 - imported by numpy.compat.py3k (optional)
missing module named numpy.eye - imported by numpy (delayed), numpy.core.numeric (delayed)
missing module named numpy.recarray - imported by numpy (top-level), numpy.ma.mrecords (top-level)
missing module named numpy.expand_dims - imported by numpy (top-level), numpy.ma.core (top-level)
missing module named numpy.array - imported by numpy (top-level), numpy.ma.core (top-level), numpy.ma.extras (top-level), numpy.ma.mrecords (top-level)
missing module named numpy.iscomplexobj - imported by numpy (top-level), numpy.ma.core (top-level)
missing module named numpy.amin - imported by numpy (top-level), numpy.ma.core (top-level)
missing module named numpy.amax - imported by numpy (top-level), numpy.ma.core (top-level)
missing module named numpy.float64 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.float32 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.uint64 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.uint32 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.uint16 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.uint8 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.int64 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.int32 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.int16 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.int8 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named _ufunc - imported by numpy._typing (conditional)
missing module named numpy.bytes_ - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.str_ - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.void - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.object_ - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.datetime64 - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.timedelta64 - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.number - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.complexfloating - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.floating - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.integer - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.ctypeslib (top-level)
missing module named numpy.unsignedinteger - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.bool_ - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.ma.core (top-level), numpy.ma.mrecords (top-level)
missing module named numpy.generic - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.dtype - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.array_api._typing (top-level), numpy.ma.mrecords (top-level), numpy.ctypeslib (top-level)
missing module named numpy.ndarray - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.ma.core (top-level), numpy.ma.extras (top-level), numpy.ma.mrecords (top-level), numpy.ctypeslib (top-level)
missing module named numpy.ufunc - imported by numpy (top-level), numpy._typing (top-level)
missing module named numpy.histogramdd - imported by numpy (delayed), numpy.lib.twodim_base (delayed)
missing module named dummy_thread - imported by cffi.lock (conditional, optional)
missing module named thread - imported by cffi.lock (conditional, optional), cffi.cparser (conditional, optional)
missing module named cStringIO - imported by cPickle (top-level), cffi.ffiplatform (optional)
missing module named copy_reg - imported by cPickle (top-level), cStringIO (top-level)
missing module named cPickle - imported by pycparser.ply.yacc (delayed, optional)
missing module named cffi._pycparser - imported by cffi (optional), cffi.cparser (optional)
missing module named defusedxml - imported by PIL.Image (optional)
missing module named Image - imported by qrcode.compat.pil (optional), kivy.core.image.img_pil (optional), docutils.parsers.rst.directives.images (optional)
missing module named roman - imported by docutils.writers.latex2e (optional), docutils.writers.manpage (optional)
missing module named 'setuptools.extern.jaraco' - imported by setuptools._reqs (top-level), setuptools._entry_points (top-level), setuptools.command.egg_info (top-level), setuptools._vendor.jaraco.text (top-level)
missing module named setuptools.extern.importlib_resources - imported by setuptools.extern (conditional), setuptools._importlib (conditional), setuptools._vendor.jaraco.text (optional)
missing module named setuptools.extern.tomli - imported by setuptools.extern (delayed), setuptools.config.pyprojecttoml (delayed)
missing module named setuptools.extern.importlib_metadata - imported by setuptools.extern (conditional), setuptools._importlib (conditional)
missing module named setuptools.extern.ordered_set - imported by setuptools.extern (top-level), setuptools.dist (top-level)
missing module named setuptools.extern.packaging - imported by setuptools.extern (top-level), setuptools.dist (top-level), setuptools.command.egg_info (top-level), setuptools.depends (top-level)
missing module named 'setuptools.extern.more_itertools' - imported by setuptools.dist (top-level), setuptools.config.expand (delayed), setuptools.config.pyprojecttoml (delayed), setuptools._itertools (top-level), setuptools._entry_points (top-level), setuptools.msvc (top-level), setuptools._vendor.jaraco.functools (top-level)
missing module named 'setuptools.extern.packaging.utils' - imported by setuptools.wheel (top-level)
missing module named 'setuptools.extern.packaging.tags' - imported by setuptools.wheel (top-level)
missing module named trove_classifiers - imported by setuptools.config._validate_pyproject.formats (optional)
missing module named 'setuptools.extern.packaging.specifiers' - imported by setuptools.config.setupcfg (top-level), setuptools.config._apply_pyprojecttoml (delayed)
missing module named 'setuptools.extern.packaging.version' - imported by setuptools.config.setupcfg (top-level)
missing module named 'setuptools.extern.packaging.markers' - imported by setuptools.config.setupcfg (top-level)
missing module named 'setuptools.extern.packaging.requirements' - imported by setuptools.config.setupcfg (top-level)
missing module named pyimod02_importers - imported by /Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py (top-level), /Users/ymq/py3/lib/python3.9/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgres.py (top-level)
missing module named Queue - imported by urllib3.util.queue (conditional), kivy.compat (optional)
missing module named ios - imported by kivy.metrics (delayed, conditional), kivy.core.window (delayed)
missing module named android.api_version - imported by android (top-level), kivy.core.audio.audio_android (top-level)
missing module named android.python_act - imported by android (top-level), kivy.core.clipboard.clipboard_android (top-level)
missing module named android.config - imported by android (optional), plyer.platforms.android (optional)
missing module named android.remove_presplash - imported by android (delayed, optional), kivy.base (delayed, optional)
missing module named android.mActivity - imported by android (delayed, conditional), kivy.core.window (delayed, conditional), kivy.app (delayed, conditional), kivy.core.window.window_sdl2 (delayed, conditional)
missing module named Leap - imported by kivy.input.providers.leapfinger (delayed)
missing module named 'pygame.joystick' - imported by kivy.input.providers.androidjoystick (conditional)
missing module named oscpy - imported by kivy.input.providers.tuio (delayed, optional)
missing module named smb - imported by kivy.loader (delayed, conditional, optional)
missing module named 'kivy.core.text._text_pango' - imported by kivy.core.text.text_pango (top-level)
missing module named 'android.runnable' - imported by kivyblocks.widgetExt.androidwebview (top-level), kivy.core.clipboard.clipboard_android (top-level)
missing module named win32file - imported by kivy.uix.filechooser (conditional, optional)
missing module named pytest - imported by ffpyplayer.tests.test_write (top-level)
missing module named 'pyobjus.dylib_manager' - imported by kivyblocks.pyinterpreter (conditional), kivy.core.clipboard.clipboard_nspaste (optional), kivy.core.audio.audio_avplayer (top-level)
missing module named pyobjus - imported by kivyblocks.pyinterpreter (conditional), kivy.core.clipboard.clipboard_nspaste (optional), kivy.core.audio.audio_avplayer (top-level)
missing module named ImageDraw - imported by qrcode.compat.pil (optional)
missing module named 'kivy.lib.gstplayer._gstplayer' - imported by kivy.lib.gstplayer (conditional)
missing module named 'android.storage' - imported by kivyblocks.blocksapp (conditional)
missing module named trio - imported by kivy.clock (delayed, conditional)
missing module named pygame - imported by kivy.app (delayed, conditional), kivy.core.text.text_pygame (optional), kivy.core.clipboard.clipboard_pygame (optional), kivy.support (delayed), kivy.core.window.window_pygame (top-level), kivy.core.image.img_pygame (optional), kivy.core.audio.audio_pygame (conditional, optional)
missing module named ConfigParser - imported by kivy.config (optional)
missing module named android_mixer - imported by kivy.core.audio.audio_pygame (conditional, optional)
missing module named 'android.mixer' - imported by kivy.core.audio.audio_pygame (conditional, optional)
missing module named cv2.cvtColor - imported by cv2 (delayed), kivy.core.camera.camera_android (delayed)
missing module named enchant - imported by kivy.core.spelling.spelling_enchant (top-level)
missing module named 'gi.repository' - imported by kivy.support (delayed, optional), kivy.core.clipboard.clipboard_gtk3 (top-level)
missing module named gi - imported by kivy.core.camera.camera_gi (top-level), kivy.core.clipboard.clipboard_gtk3 (top-level)
missing module named gobject - imported by kivy.support (delayed, optional)
missing module named dbus - imported by kivy.core.clipboard.clipboard_dbusklipper (optional)
missing module named win32gui - imported by kivy.core.window.window_pygame (delayed)
missing module named picamera - imported by kivy.core.camera.camera_picamera (top-level)
missing module named ffmpeg - imported by kivy.core.video.video_ffmpeg (optional)
missing module named kivy.lib.vidcore_lite.egl - imported by kivy.lib.vidcore_lite (top-level), kivy.core.window.window_egl_rpi (top-level)
missing module named kivy.lib.vidcore_lite.bcm - imported by kivy.lib.vidcore_lite (top-level), kivy.core.window.window_egl_rpi (top-level)
missing module named AppKit - imported by kivy.core.spelling.spelling_osxappkit (top-level)
missing module named 'pygame.scrap' - imported by kivy.core.clipboard.clipboard_pygame (optional)
missing module named 'opencv.highgui' - imported by kivy.core.camera.camera_opencv (optional)
missing module named opencv - imported by kivy.core.camera.camera_opencv (optional)
missing module named kivy_deps - imported by kivy (optional)
missing module named simplejson - imported by requests.compat (conditional, optional)
missing module named StringIO - imported by urllib3.packages.six (conditional)
runtime module named urllib3.packages.six.moves - imported by http.client (top-level), urllib3.util.response (top-level), urllib3.connectionpool (top-level), 'urllib3.packages.six.moves.urllib' (top-level), urllib3.util.queue (top-level)
missing module named brotlicffi - imported by urllib3.util.request (optional), urllib3.response (optional)
missing module named "'urllib3.packages.six.moves.urllib'.parse" - imported by urllib3.request (top-level), urllib3.poolmanager (top-level)
missing module named socks - imported by urllib3.contrib.socks (optional)
missing module named cryptography.x509.UnsupportedExtension - imported by cryptography.x509 (optional), urllib3.contrib.pyopenssl (optional)
missing module named urllib3_secure_extra - imported by urllib3 (optional)

File diff suppressed because it is too large Load Diff

BIN
client/macos/dist/kboss_customer vendored Executable file

Binary file not shown.

View File

@ -0,0 +1,44 @@
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['../main.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='kboss_customer',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)

112
client/main.py Executable file
View File

@ -0,0 +1,112 @@
# encoding: utf-8
import asyncio
import os
# os.environ['KIVY_GL_BACKEND'] = 'angle_sdl2'
from functools import partial
import codecs
from threading import Thread
import json
os.environ["KIVY_VIDEO"] = "ffpyplayer"
import sys
from traceback import print_exc
import requests
from functools import partial
import kivy
import kivyblocks
from kivy.config import Config
from kivy.resources import resource_add_path
resource_add_path(os.path.join(os.path.dirname(kivyblocks.__file__),'./ttf'))
Config.set('kivy', 'default_font', [
'msgothic',
'DroidSansFallback.ttf'])
from kivy.app import App
from kivy.utils import platform
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.logger import Logger
from kivy.uix.label import Label
from kivy.factory import Factory
from kivy.uix.boxlayout import BoxLayout
import plyer
from appPublic.folderUtils import ProgramPath
from appPublic.jsonConfig import getConfig
from appPublic.Singleton import GlobalEnv
from appPublic.uniqueID import getID
from appPublic.registerfunction import RegisterFunction
from kivyblocks.blocksapp import BlocksApp
from kivyblocks.blocks import registerWidget, Blocks
from kivyblocks.pagescontainer import PageContainer
from kivyblocks.utils import *
from kivyblocks.dg import DataGrid
from kivyblocks.baseWidget import *
from kivyblocks.threadcall import HttpClient
from appPublic.find_player import BroadcastServer, find_players
from appPublic.background import Background
from kivyblocks.player_osc import PlayerOSCServer
from kivyblocks.threadcall import Workers
from kivyblocks.eventhandler import eventhandler
from loadplugins import load_plugins
r = Factory.register
def changeDesktopFontSize():
desktopOSs=[
"win",
"linux",
"macosx"
]
if not platform in desktopOSs:
return
config = getConfig()
d = {k:v+3.0 for k,v in config.font_sizes.items()}
config.font_sizes = d
class IptvApp(BlocksApp):
def build(self):
load_plugins(ProgramPath())
x = super().build()
loop = asyncio.get_event_loop()
loop.call_later(3, cotest)
return x
def play(self, url):
w = Blocks.getWidgetById('vplayer', from_widget=self.root)
if w:
w.set_source(url)
def vplayer_stop(self, o, from_widget):
w = Blocks.getWidgetById('vplayer', from_widget=from_widget)
if w:
w.on_state(w, 'pause')
def vplayer_play(self, o, from_widget):
w = Blocks.getWidgetById('vplayer', from_widget=from_widget)
if w:
w.on_state(w, 'play')
@eventhandler
async def cotest():
await asyncio.sleep(2)
print('after 2 seconds')
if __name__ == '__main__':
pp = workdir = ProgramPath()
print('ProgramPath=',pp,'workdir=',workdir)
config = getConfig(workdir,NS={'workdir':workdir,'ProgramPath':pp})
changeDesktopFontSize()
myapp = IptvApp()
ge = GlobalEnv()
# Window.maximize()
loop = asyncio.get_event_loop()
loop.run_until_complete(myapp.async_run())
# myapp.run()

1
client/version.py Executable file
View File

@ -0,0 +1 @@
__version__ = "0.1.0"

78
conf/config.json Executable file
View File

@ -0,0 +1,78 @@
{
"logger":{
"name":"iptv",
"levelname":"debug",
"logfile":"$[workdir]$/logs/iptv.log"
},
"definitions":{
"rbacdb":"iptvdb"
},
"filesroot":"$[workdir]$/files",
"databases":{
"iptvdb":{
"driver":"aiomysql",
"async_mode":true,
"coding":"utf8",
"dbname":"iptvdb",
"maxconn":100,
"kwargs":{
"user":"test",
"db":"iptvdb",
"password":"QUZVcXg5V1p1STMybG5Ia6mX9D0v7+g=",
"host":"localhost"
}
}
},
"website":{
"paths":[
["$[workdir]$/wwwroot",""]
],
"client_max_size":10000,
"host":"0.0.0.0",
"port":10180,
"coding":"utf-8",
"ssl_gg":{
"crtfile":"$[workdir]$/conf/www.bsppo.com.pem",
"keyfile":"$[workdir]$/conf/www.bsppo.com.key"
},
"indexes":[
"index.html",
"index.tmpl",
"index.ui",
"index.dspy",
"index.md"
],
"processors":[
[".ws","ws"],
[".xterm","xterm"],
[".proxy","proxy"],
[".llm", "llm"],
[".xlsxds","xlsxds"],
[".sqlds","sqlds"],
[".tmpl.js","tmpl"],
[".tmpl.css","tmpl"],
[".html.tmpl","tmpl"],
[".bcrud", "bricks_crud"],
[".tmpl","tmpl"],
[".bui","bui"],
[".ui","bui"],
[".dspy","dspy"],
[".md","md"]
],
"rsakey":{
"privatekey":"$[workdir]$/conf/rsa_private_key.pem",
"publickey":"$[workdir]$/conf/rsa_public_key.pem"
},
"session_max_time":3000,
"session_issue_time":2500,
"session_redis_oops":{
"url":"redis://127.0.0.1:6379"
}
},
"langMapping":{
"zh-Hans-CN":"zh-cn",
"zh-CN":"zh-cn",
"en-us":"en",
"en-US":"en"
}
}

13
conf/t.sql Normal file
View File

@ -0,0 +1,13 @@
select a.*, b.providerid, b.productid, b.discount, b.price
from saleprotocol a, product_salemode b
where a.offer_orgid='3'
and a.bid_orgid='*'
and b.protocolid=a.id
and b.providerid='8'
and (b.productid='1' or b.productid = '*')
and a.start_date <= '2023-06-29'
and a.end_date > '2023-06-29'
and a.del_flg = '0'
and b.del_flg = '0'
order by productid desc

13
iptvd.service Normal file
View File

@ -0,0 +1,13 @@
[Unit]
Description=iptv service
Documention=
After=mariadb.service
Wants=systemd-networkd.service
Requires=nginx.service
[Service]
Type=forking
ExecStart=su - ymq -c "python3 $HOME/py/gadget/gadget/gadget.py -w $HOME/iptv >> /tmp/iptv.log 2>&1 &"
[Install]
WantedBy=multi-user.target

78
m3u.py Normal file
View File

@ -0,0 +1,78 @@
import codecs
def tvgParser(txt):
d = {}
buf = ''
k = ''
inbrace = False
for c in txt:
if c == '"':
if inbrace:
inbrace = False
d[k] = buf
buf = ''
k = ''
else:
inbrace = True
continue
if c == '=':
k = buf
buf = ''
continue
if c == ' ':
if inbrace:
buf = '%s%s' % (buf,c)
continue
buf = '%s%s' % (buf,c)
if k != '':
v = buf
d[k] = v
return d
def channelInfo(l):
g = {}
e = l.split(',')
info = e[-2]
fo=info.split(' ',1)
if len(fo) == 2:
_,tvginfo=info.split(' ',1)
g = tvgParser(tvginfo)
g['name'] = e[-1]
return g
def m3uParser(text):
text = ''.join(text.split('\r'))
newchannel = False
channels = []
for i,line in enumerate(text.split('\n')):
if i==0 and not line.startswith('#EXTM3U'):
return None
if i == 0:
continue
if line == '':
continue
if line.startswith('#EXTINF'):
channel = channelInfo(line)
status = 'url'
continue
if line.startswith('http://') or line.startswith('https://'):
channel['url'] = line
channels.append(channel)
continue
return channels
def testfile(filename):
with codecs.open(filename,'r','utf-8') as f:
text = f.read()
m3uParser(text)
if __name__ == '__main__':
import sys
testfile(sys.argv[1])

BIN
models/appcodes.xlsx Normal file

Binary file not shown.

BIN
models/appcodes_kv.xlsx Normal file

Binary file not shown.

BIN
models/channelfailed.xlsx Normal file

Binary file not shown.

BIN
models/device.xlsx Normal file

Binary file not shown.

BIN
models/iptvchannels.xlsx Normal file

Binary file not shown.

505
models/mysql.ddl.sql Normal file
View File

@ -0,0 +1,505 @@
-- ./iptvchannels.xlsx
drop table if exists iptvchannels;
CREATE TABLE iptvchannels
(
`id` VARCHAR(32) comment '编号',
`tv_group` VARCHAR(500) comment '频道组',
`tv_name` VARCHAR(500) comment '频道名称',
`logo_url` VARCHAR(1000) comment '台标url',
`url` VARCHAR(1000) comment 'url',
`media_type` VARCHAR(100) comment '媒体类型',
`download_date` VARCHAR(10) comment '下载日期',
`channel_delay` int comment '频道延迟',
`channel_grade` int comment '频道等级',
`del_flg` VARCHAR(1) comment '删除标志'
,primary key(id)
)
engine=innodb
default charset=utf8
comment 'IPTV频道清单'
;
CREATE INDEX iptvchannels_idx1 ON iptvchannels(tv_group);
CREATE INDEX iptvchannels_idx2 ON iptvchannels(tv_name);
CREATE UNIQUE INDEX iptvchannels_idx3 ON iptvchannels(url);
-- ./userapikey.xlsx
drop table if exists userapikey;
CREATE TABLE userapikey
(
`id` VARCHAR(32) comment 'id',
`providerid` VARCHAR(200) comment '供应商id',
`customerid` VARCHAR(32) DEFAULT '0' comment '用户id',
`apikey` VARCHAR(4000) DEFAULT '0' comment 'api密钥',
`secretkey` VARCHAR(4000) comment '附属密钥',
`rfname` VARCHAR(400) comment '函数名'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '用户api密码表'
;
CREATE UNIQUE INDEX userapikey_idx1 ON userapikey(providerid,customerid);
CREATE INDEX userapikey_idx2 ON userapikey(customerid);
-- ./userroles.xlsx
drop table if exists userrole;
CREATE TABLE userrole
(
`id` VARCHAR(32) comment '用户id',
`userid` VARCHAR(32) comment '用户id',
`roleid` VARCHAR(32) comment '角色id'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '用户角色'
;
-- ./appcodes_kv.xlsx
drop table if exists appcodes_kv;
CREATE TABLE appcodes_kv
(
`id` VARCHAR(32) comment 'id',
`parentid` VARCHAR(32) comment '父id',
`k` VARCHAR(32) comment '',
`v` VARCHAR(255) comment ''
,primary key(id)
)
engine=innodb
default charset=utf8
comment '编码键值表'
;
CREATE UNIQUE INDEX appcodes_kv_idx1 ON appcodes_kv(parentid,k);
CREATE INDEX appcodes_kv_idx2 ON appcodes_kv(parentid);
insert into appcodes_kv (id,parentid,k,v) values ('code0001','resp_mode','0','stream');
insert into appcodes_kv (id,parentid,k,v) values ('code0002','resp_mode','1','sync');
insert into appcodes_kv (id,parentid,k,v) values ('code0003','resp_mode','2','async');
insert into appcodes_kv (id,parentid,k,v) values ('code0004','params_type','0','model');
insert into appcodes_kv (id,parentid,k,v) values ('code0005','params_type','1','modelinstance');
insert into appcodes_kv (id,parentid,k,v) values ('code0006','params_type','2','user');
insert into appcodes_kv (id,parentid,k,v) values ('code0007','params_type','3','session');
insert into appcodes_kv (id,parentid,k,v) values ('code0008','code_hierarchy','0','one l');
insert into appcodes_kv (id,parentid,k,v) values ('code0009','code_hierarchy','1','hierarchy');
insert into appcodes_kv (id,parentid,k,v) values ('code0010','minimax_acc_status','0','enabled');
insert into appcodes_kv (id,parentid,k,v) values ('code0011','minimax_acc_status','2','disabled');
insert into appcodes_kv (id,parentid,k,v) values ('code0012','datatype','str','str');
insert into appcodes_kv (id,parentid,k,v) values ('code0013','datatype','char','char');
insert into appcodes_kv (id,parentid,k,v) values ('code0014','datatype','short','short');
insert into appcodes_kv (id,parentid,k,v) values ('code0015','datatype','long','long');
insert into appcodes_kv (id,parentid,k,v) values ('code0016','datatype','llong','llong');
insert into appcodes_kv (id,parentid,k,v) values ('code0017','datatype','date','date');
insert into appcodes_kv (id,parentid,k,v) values ('code0018','datatype','time','time');
insert into appcodes_kv (id,parentid,k,v) values ('code0019','datatype','timestamp','timestamp');
insert into appcodes_kv (id,parentid,k,v) values ('code0020','datatype','float','float');
insert into appcodes_kv (id,parentid,k,v) values ('code0021','datatype','double','double');
insert into appcodes_kv (id,parentid,k,v) values ('code0022','datatype','ddouble','ddouble');
insert into appcodes_kv (id,parentid,k,v) values ('code0023','datatype','decimal','decimal');
insert into appcodes_kv (id,parentid,k,v) values ('code0024','uitype','str','str');
insert into appcodes_kv (id,parentid,k,v) values ('code0025','uitype','text','text');
insert into appcodes_kv (id,parentid,k,v) values ('code0026','uitype','date','date');
insert into appcodes_kv (id,parentid,k,v) values ('code0027','uitype','int','int');
insert into appcodes_kv (id,parentid,k,v) values ('code0028','uitype','float','float');
insert into appcodes_kv (id,parentid,k,v) values ('code0029','uitype','file','file');
insert into appcodes_kv (id,parentid,k,v) values ('code0030','uitype','email','email');
insert into appcodes_kv (id,parentid,k,v) values ('code0031','uitype','tel','tel');
insert into appcodes_kv (id,parentid,k,v) values ('code0032','uitype','audiotext','audiotext');
insert into appcodes_kv (id,parentid,k,v) values ('code0033','uitype','password','password');
insert into appcodes_kv (id,parentid,k,v) values ('code0034','uitype','checkbox','checkbox');
insert into appcodes_kv (id,parentid,k,v) values ('code0035','uitype','check','check');
insert into appcodes_kv (id,parentid,k,v) values ('code0036','uitype','code','code');
insert into appcodes_kv (id,parentid,k,v) values ('code0037','yesno','1','yes');
insert into appcodes_kv (id,parentid,k,v) values ('code0038','yesno','0','no');
insert into appcodes_kv (id,parentid,k,v) values ('code0039','org_type','0','personal');
insert into appcodes_kv (id,parentid,k,v) values ('code0040','org_type','1','organization');
-- ./appcodes.xlsx
drop table if exists appcodes;
CREATE TABLE appcodes
(
`id` VARCHAR(32) comment 'id',
`name` VARCHAR(255) comment '编码名称',
`hierarchy_flg` VARCHAR(1) comment '多级标志'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '应用编码表'
;
insert into appcodes (id,name,hierarchy_flg) values ('resp_mode','返回模式','0');
insert into appcodes (id,name,hierarchy_flg) values ('params_type','参数类型','0');
insert into appcodes (id,name,hierarchy_flg) values ('code_hierarchy','编码层次','0');
insert into appcodes (id,name,hierarchy_flg) values ('minimax_acc_status','minimax账户状态','0');
insert into appcodes (id,name,hierarchy_flg) values ('datatype','数据类型','0');
insert into appcodes (id,name,hierarchy_flg) values ('uitype','UI类型','0');
insert into appcodes (id,name,hierarchy_flg) values ('yesno','是否选项','0');
insert into appcodes (id,name,hierarchy_flg) values ('org_type','机构类型','0');
-- ./userdepartment.xlsx
drop table if exists userdepartment;
CREATE TABLE userdepartment
(
`id` VARCHAR(32) comment 'id',
`userid` VARCHAR(32) comment '用户id',
`depid` VARCHAR(32) comment '部门id',
`del_flg` VARCHAR(1) DEFAULT '0' comment '删除标志',
`create_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '创建时间戳'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '用户部门表'
;
-- ./tags.xlsx
drop table if exists tags;
CREATE TABLE tags
(
`id` VARCHAR(32) comment 'id',
`userid` VARCHAR(32) comment '用户id',
`tag` VARCHAR(400) comment '标签名称'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '标签表'
;
-- ./userapp.xlsx
drop table if exists userapp;
CREATE TABLE userapp
(
`id` VARCHAR(32) comment 'id',
`userid` VARCHAR(32) DEFAULT '0' comment '用户id',
`appname` VARCHAR(99) comment '应用名称',
`apikey` VARCHAR(400) comment 'apikey'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '用户应用'
;
-- ./permission.xlsx
drop table if exists permission;
CREATE TABLE permission
(
`id` VARCHAR(32) comment '权限id',
`name` VARCHAR(255) comment '名称',
`description` VARCHAR(255) comment '描述',
`ptype` VARCHAR(20) comment '类型',
`parentid` VARCHAR(32) comment '父权限id',
`path` VARCHAR(255) comment '路径',
`title` VARCHAR(255) comment '标题',
`icon` VARCHAR(255) comment '图标'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '权限'
;
CREATE INDEX permission_idx1 ON permission(ptype);
CREATE INDEX permission_idx2 ON permission(parentid);
-- ./taging.xlsx
drop table if exists taging;
CREATE TABLE taging
(
`id` VARCHAR(32) comment 'id',
`channelid` VARCHAR(32) comment '频道id',
`tagid` VARCHAR(32) comment '标签id'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '打标签'
;
-- ./device.xlsx
drop table if exists device;
CREATE TABLE device
(
`id` VARCHAR(32) comment 'id',
`name` VARCHAR(255) comment '设备名称',
`takeover_flg` VARCHAR(1) comment '接管标志',
`userid` VARCHAR(32) comment '用户id'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '设备表'
;
-- ./users.xlsx
drop table if exists users;
CREATE TABLE users
(
`id` VARCHAR(32) comment '用户id',
`username` VARCHAR(255) comment '用户名',
`name` VARCHAR(255) comment '姓名',
`password` VARCHAR(255) comment '密码',
`email` VARCHAR(255) comment '邮件地址',
`orgid` VARCHAR(32) comment '所属机构',
`nick_name` VARCHAR(255) comment '显示名',
`address` VARCHAR(255) comment '地址',
`mobile` VARCHAR(255) comment '手机',
`user_status` VARCHAR(1) DEFAULT '0' comment '用户状态'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '用户'
;
CREATE INDEX users_idx1 ON users(orgid);
CREATE UNIQUE INDEX users_idx2 ON users(username);
insert into users (id,username,password) values (' HappyCat123',' HappyCat123','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' GreenForest456',' GreenForest456','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' SunnySky789',' SunnySky789','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' OceanWave246',' OceanWave246','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' BraveLion135',' BraveLion135','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' MagicStar987',' MagicStar987','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' HappyFox654',' HappyFox654','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' RedSunshine321',' RedSunshine321','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' BlueMoon852',' BlueMoon852','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' WiseOwl963',' WiseOwl963','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' SilverCloud741',' SilverCloud741','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' GoldenEagle258',' GoldenEagle258','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' QuickTiger369',' QuickTiger369','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' SmartBear147',' SmartBear147','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' GentleBreeze852',' GentleBreeze852','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' FlyingHawk753',' FlyingHawk753','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' LuckyFish159',' LuckyFish159','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' BrightStar246',' BrightStar246','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' BoldWolf789',' BoldWolf789','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' ShinyGem963',' ShinyGem963','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' PeacefulDove357',' PeacefulDove357','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' NobleKnight456',' NobleKnight456','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' CleverRabbit852',' CleverRabbit852','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' MysticRiver159',' MysticRiver159','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' SilentSnow753',' SilentSnow753','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' JoyfulBird369',' JoyfulBird369','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' StrongBull258',' StrongBull258','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' CalmSea147',' CalmSea147','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' HonestSheep963',' HonestSheep963','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' PlayfulPuppy357',' PlayfulPuppy357','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' GlowingSun147',' GlowingSun147','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' SweetCherry456',' SweetCherry456','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' DreamySky852',' DreamySky852','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' FriendlyDuck963',' FriendlyDuck963','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' KindElephant741',' KindElephant741','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' HappyWhale258',' HappyWhale258','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' GracefulSwan159',' GracefulSwan159','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' BraveEagle753',' BraveEagle753','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' GentleRabbit369',' GentleRabbit369','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' SunnyMeadow852',' SunnyMeadow852','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' WiseLion147',' WiseLion147','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' SilverMountain456',' SilverMountain456','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' MysticMoon852',' MysticMoon852','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' ShinyStar963',' ShinyStar963','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' PeacefulTree357',' PeacefulTree357','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' GoldenRiver741',' GoldenRiver741','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' BoldHawk258',' BoldHawk258','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' BrightLeaf159',' BrightLeaf159','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' SmartPanda753',' SmartPanda753','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' SilentOcean369',' SilentOcean369','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' LuckyBear852',' LuckyBear852','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' QuickFox147',' QuickFox147','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' HappyDeer456',' HappyDeer456','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' GreenValley852',' GreenValley852','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' CalmRiver963',' CalmRiver963','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' HonestHawk357',' HonestHawk357','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' PlayfulCat147',' PlayfulCat147','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' GlowingStar456',' GlowingStar456','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' FriendlySheep852',' FriendlySheep852','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' NobleFox963',' NobleFox963','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' DreamyWhale741',' DreamyWhale741','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' KindDove258',' KindDove258','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
insert into users (id,username,password) values (' GentleBear159',' GentleBear159','QUZVcXg5V1p1STMybG5Ia+zDtngv7A==');
-- ./channelfailed.xlsx
drop table if exists channelfailed;
CREATE TABLE channelfailed
(
`id` VARCHAR(32) comment 'id',
`deviceid` VARCHAR(32) comment '设备id',
`channelid` VARCHAR(32) comment '频道id',
`reporttime` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '报告时间'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '频道播放失败'
;
-- ./playhistory.xlsx
drop table if exists playhistory;
CREATE TABLE playhistory
(
`id` VARCHAR(32) comment 'id',
`deviceid` VARCHAR(32) comment '设备id',
`channelid` VARCHAR(32) comment '频道id',
`playtime` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '开始时间'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '播放历史'
;

BIN
models/permission.xlsx Normal file

Binary file not shown.

BIN
models/playhistory.xlsx Normal file

Binary file not shown.

BIN
models/taging.xlsx Normal file

Binary file not shown.

BIN
models/tags.xlsx Normal file

Binary file not shown.

BIN
models/userapikey.xlsx Normal file

Binary file not shown.

BIN
models/userapp.xlsx Normal file

Binary file not shown.

BIN
models/userdepartment.xlsx Normal file

Binary file not shown.

BIN
models/userroles.xlsx Normal file

Binary file not shown.

BIN
models/users.xlsx Normal file

Binary file not shown.

62
script/iptv.nginx Normal file
View File

@ -0,0 +1,62 @@
server {
autoindex on;
client_max_body_size 20m;
server_name pd4e.com;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Url "$scheme://$host:$server_port$request_uri";
index index.html index.htm;
location ~^/ip$ {
return 200 "$remote_addr";
}
location /wss/ {
proxy_pass http://localhost:10081/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Path 'wss';
}
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Origin *;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-real-ip $remote_addr;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
proxy_pass http://localhost:10080/;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/pd4e.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/pd4e.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = pd4e.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name pd4e.com;
return 404; # managed by Certbot
}

14
script/iptv.service Normal file
View File

@ -0,0 +1,14 @@
[Unit]
Description=sage service
Documention=sage service to control sage service start or stoop
After=mariadb.service
Wants=systemd-networkd.service
Requires=nginx.service
[Service]
Type=forking
ExecStart=su - ymq -c "py/iptv/script/run.sh"
ExecStop=su - ymq "bin/killname iptv.py"
[Install]
WantedBy=multi-user.target

6
script/run.sh Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/bash
$HOME/bin/killname /py/iptv/app/iptv.py
$HOME/py3/bin/python $HOME/py/iptv/app/iptv.py -w $HOME/py/iptv >$HOME/py/iptv/logs/stderr.log 2>&1 &
$HOME/py3/bin/python $HOME/py/iptv/app/iptv.py -w $HOME/py/iptv -p 10181 >>$HOME/py/iptv/logs/stderr.log 2>&1 &
exit 0

30
wwwroot/add_channels.dspy Normal file
View File

@ -0,0 +1,30 @@
url = params_kw.m3u_url
debug(f'{params_kw=}, {url=}')
try:
x = await load_url_iptv('iptv', url, 'iptvdb')
return {
"widgettype":"Message",
"options":{
"cwidth":21,
"cheight":15,
"archor":"cc",
"auto_open":true,
"auto_dismiss":true,
"title":"Success",
"message":"add success"
}
}
except Exception as e:
exception(f'{e=}')
return {
"widgettype":"Error",
"options":{
"cwidth":21,
"cheight":15,
"archor":"cc",
"auto_open":true,
"auto_dismiss":true,
"title":"Error",
"message":str(e)
}
}

67
wwwroot/add_channels.ui Normal file
View File

@ -0,0 +1,67 @@
{
"widgettype":"PopupWindow",
"options":{
"width":"80%",
"cheight":16,
"widget":"center",
"auto_open":true,
"moving":true,
"modal":true,
"archor":"cc",
"icon":"/imgs/tv.png",
"title":"添加频道"
},
"subwidgets":[
{
"widgettype":"VBox",
"options":{
"width":"100%",
"height":"100%"
},
"subwidgets":[
{
"widgettype":"Text",
"options":{
"otext":"we can ONLY import m3u8 channels in m3u format, please input m3u url"
,"i18n":true,
"wrap":true,
"rate":1.5,
"dynsize":true
}
},
{
"widgettype":"Form",
"id":"form",
"options":{
"fields":[
{
"name":"m3u_url",
"uitype":"str"
}
]
},
"binds":[
{
"wid":"self",
"event":"submit",
"actiontype":"urlwidget",
"target":"self",
"options":{
"url":"{{entire_url('add_channels.dspy')}}"
}
}
]
}
]
}
],
"binds":[
{
"wid":"form",
"event":"submit",
"actiontype":"method",
"target":"self",
"method":"dismiss"
}
]
}

25
wwwroot/api/channels.dspy Executable file
View File

@ -0,0 +1,25 @@
sql = "select * from iptvchannels where del_flg='0'"
ns = {
}
ns = params_kw.copy()
ns['sort'] = 'tv_name'
parts = []
tv_name = params_kw.get('tv_name', None)
if tv_name:
tv_name = '%' + tv_name + '%'
parts.append(' tv_name like ${tv_name}$ ')
ns['tv_name'] = tv_name
if len(parts) > 0:
sql += ' and ' + 'and'.join(parts)
sql += ' order by tv_group, tv_name'
db=DBPools()
if not params_kw.get('page'):
ns['page'] = 1
ns['rows'] = 100
async with db.sqlorContext('iptvdb') as sor:
recs = await sor.sqlPaging(sql, ns)
return recs

29
wwwroot/api/delete.dspy Normal file
View File

@ -0,0 +1,29 @@
sql = "update iptvchannels set del_flg='1' where id=${id}$"
ns = params_kw.copy()
db=DBPools()
async with db.sqlorContext('iptvdb') as sor:
recs = await sor.sqlPaging(sql, ns)
return {
"widgettype":"Message",
"options":{
"title":"Channel deleted",
"message":f"{ns['id']=} channel deleted",
"timeout':2,
"archor":"rt",
"auto_open":True,
"auto_dismiss":True
}
}
return {
"widgettype":"Error",
"options":{
"title":"Delete failed",
"message":"Delete channel[id={ns['id']}] error",
"timeout":2,
"archor":"rt",
"auto_open":True,
"auto_dismiss":True
}
}

View File

@ -0,0 +1,26 @@
id = params_kw.get('id')
if id:
db = DBPools()
async with db.sqlorContext('iptvdb') as sor:
sql = "update iptvchannels set del_flg='1' where id=${id}$"
await sor.sqlExe(sql, {'id':id})
return {
"widgettype":"Message",
"options":{
"timeout":2,
"archor":"tc",
"title":"Delete success",
"message":f"channel[{id=} deleted"
}
}
return {
"widgettype":"Error",
"options":{
"timeout":2,
"archor":"tc",
"title":params_kw.get('tv_name'),
"height":"80px",
"message":f"Delete {id=} failed"
}
}

6
wwwroot/api/get_tv_groups.dspy Executable file
View File

@ -0,0 +1,6 @@
db = DBPools()
async with db.sqlorContext('iptvdb') as sor:
recs = await sor.sqlExe("select distinct tv_group from iptvchannels",{})
return recs

1
wwwroot/api/index.dspy Normal file
View File

@ -0,0 +1 @@
return "noting in here"

100
wwwroot/atvoe.js Normal file
View File

@ -0,0 +1,100 @@
atvoe = window.atvoe || {};
atvoe.TVSet = class extends bricks.HBox {
constructor(opts){
super(opts);
this.tv_icon = new bricks.Icon({
url:'/imgs/tv.png',
rate:5
});
this.txt_w = new bricks.Text({text:opts.name || opts.id});
this.add_widget(this.tv_icon);
this.add_widget(this.txt_w);
}
}
atvoe.RTCBox = class extends bricks.VBox {
constructor(opts){
super(opts);
this.tvs_w = new bricks.HBox({cheight:5});
this.tvs_w.set_style('scroll', 'auto');
this.ctrl_w = new bricks.HBox({cheight:2});
this.channels_w = new bricks.Filler({});
this.add_widget(this.tvs_w);
this.add_widget(this.ctrl_w);
this.add_widget(this.channels_w);
schedule_once(this.connect_wss.bind(this), 0.2);
}
loseWSSconnect(){
var w = new bricks.Error({
title:'Error',
message:'websocket connection lose',
timeout:5
})
w.open();
}
async dc_msg(dc, msg){
console.log('dc_msg(), msg:', msg);
}
async connect_wss(){
this.deviceid = bricks.deviceid('atvoe');
this.info = await bricks.jc.get(this.info_url, {
params:{
id:this.deviceid
}
});
this.signaling = new bricks.Signaling({
signaling_url:'wss://atvoe.com/wss/ws/rtc_signaling.ws',
info:this.info,
onlogin:this.show_tvs.bind(this),
onclose:this.loseWSSconnect.bind(this),
connect_opts:{
on_dc_open:this.rc_tvset.bind(this),
on_dc_message:this.dc_msg.bind(this),
on_pc_connected:this.pc_connected.bind(this),
on_pc_disconnected:this.pc_disconnected.bind(this),
data_connect:true,
media_options:{
video:true,
audio:true
},
ice_servers:[
{
"urls":"stun:stun.open-computing.cn:13478"
}, {
"urls":"turn:stun.open-computing.cn:13479",
"username":"turn",
"credential":"server"
}
]
}
});
this.signaling.add_sessionhandler('p2p', bricks.RTCP2PConnect);
}
async pc_connected(peer){
console.log('-----connected to peer');
}
async pc_disconnected(peer){
console.log('-----disconnected from peer');
}
async show_tvs(peers){
console.log('online peers=', peers);
this.tvs_w.clear_widgets();
peers.forEach(p => {
var tv = new atvoe.TVSet(p);
tv.bind('click', this.connect_tvset.bind(this, p))
this.tvs_w.add_widget(tv);
});
}
connect_tvset(peer){
this.remote_tv = peer;
this.signaling.new_session('p2p', peer);
}
async rc_tvset(dc){
console.log('rc_tvset() called ....', arguments);
this.pc_dc = dc;
this.build_controller();
}
build_controller(){
}
}
bricks.Factory.register('RTCBox', atvoe.RTCBox);

14
wwwroot/bottom.ui Normal file
View File

@ -0,0 +1,14 @@
{
"widgettype":"HBox",
"options":{
"cheight":2.5
},
"subwidgets":[
{
"widgettype":"Text",
"options":{
"text":"© 2024 版权所有, 慢龟终至"
}
}
]
}

55
wwwroot/channels.ui Normal file
View File

@ -0,0 +1,55 @@
{
"id":"channel_list",
"widgettype":"Tabular",
"options":{
"data_url":"{{entire_url('/api/channels.dspy')}}",
"noheader":true,
"row_options":{
"fields":[
{
"name":"logo_url",
"cwidth":2,
"cheight":2,
"uitype":"icon",
"label":"Icon",
"value":"${logo_url}"
},
{
"name":"tv_name",
"uitype":"str",
"lable":"Channel",
"cwidth":50,
"value":"${tv_name}"
}
],
"alters":{
"logo_url":{
"cwidth":2.5
},
"tv_name":{
"cwidth":20
}
},
"cheight":2.5,
"width":"100%"
},
"page_rows":80,
"cache_limit":5
},
"binds":[
{
"wid":"self",
"event":"row_selected",
"actiontype":"script",
"target":"root.mytv",
"script":"this.setValue(params)"
},
{
"wid":"self",
"event":"row_selected",
"actiontype":"script",
"target":"root.popup",
"script":"this.dismiss()"
}
]
}

View File

@ -0,0 +1,25 @@
async def getDeviceLastPlay(deviceid):
db = DBPools()
async with db.sqlorContext('iptvdb') as sor:
recs = await sor.R('device', {'id':deviceid})
if len(recs) < 1:
await sor.C('device', {'id':deviceid})
return None
sql = "select a.deviceid, b.* from playhistory a, iptvchannels b where a.channelid = b.id and a.deviceid = ${deviceid}$ order by playtime desc"
recs = await sor.sqlExe(sql, {'deviceid':deviceid})
if len(recs) < 1:
return None
return recs[0]
debug(f'get_default_iptv.dspy:{params_kw=}')
rec = await getDeviceLastPlay(params_kw.deviceid)
if rec:
return rec
db = DBPools()
async with db.sqlorContext('iptvdb') as sor:
sql = "select * from iptvchannels order by download_date desc"
recs = await sor.sqlExe(sql, {})
i = random.randint(0, 10)
return recs[i]

15
wwwroot/get_device.dspy Normal file
View File

@ -0,0 +1,15 @@
deviceid = params_kw.get('id')
db = DBPools()
async with db.sqlorContext('iptvdb') as sor:
recs = await sor.R('device', {'id':deviceid})
if len(recs) < 1:
await sor.C('device', {'id':deviceid})
return {
"id":deviceid
}
return recs[0]
return {
"id":deviceid
}

39
wwwroot/header.ui Normal file
View File

@ -0,0 +1,39 @@
{
"widgettype":"HBox",
"options":{
"cheight":2
},
"subwidgets":[
{
"widgettype":"Icon",
"options":{
"url":"{{entire_url('/imgs/tv.png')}}",
"cursor":"pointer",
"rate":1.5
},
"binds":[
{
"wid":"self",
"event":"click",
"actiontype":"urlwidget",
"target":"app",
"mode":"append",
"options":{
"url":"{{entire_url('popupmenu.ui')}}"
}
}
]
},
{
"id":"cur_tag",
"widgettype":"Title4",
"options":{
"height":"auto",
"otext":"{{params_kw.get('tagname','Liked')}}",
"i18n":true,
"wrap":true
}
}
]
}

BIN
wwwroot/imgs/tv.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

1
wwwroot/index.dspy Normal file
View File

@ -0,0 +1 @@
return "noting in here"

34
wwwroot/index.ui Normal file
View File

@ -0,0 +1,34 @@
{
"widgettype":"VBox",
"options":{
"width":"100%",
"height":"100%"
},
"subwidgets":[
{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('header.ui')}}"
}
},
{
"id":"center",
"widgettype":"Filler",
"options":{},
"subwidgets":[
{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('iptv.ui')}}"
}
}
]
},
{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('bottom.ui')}}"
}
}
]
}

13
wwwroot/iptv.ui Normal file
View File

@ -0,0 +1,13 @@
{
"id":"mytv",
"widgettype":"Iptv",
"options":{
"widht":"100%",
"height":"100%",
"autoplay":true,
"autounmute":true,
"playok_url":"{{entire_url('report_playing.dspy')}}",
"playfailed_url":"{{entire_url('report_failed.dspy')}}",
"iptv_data_url":"{{entire_url('get_default_iptv.dspy')}}"
}
}

31
wwwroot/iptvchannels.ui Normal file
View File

@ -0,0 +1,31 @@
{
"id":"popup",
"widgettype":"PopupWindow",
"options":{
"cwidth":18,
"height":"80%",
"widget":"center",
"auto_open":true,
"modal":true,
"archor":"tl",
"icon":"/imgs/tv.png",
"title":"频道管理"
},
"subwidgets":[
{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('search_channels.ui')}}"
}
}
],
"binds":[
{
"wid":"channel_list",
"event":"row_selected",
"actiontype":"script",
"target":"self",
"script":"this.dismiss()"
}
]
}

View File

@ -0,0 +1,27 @@
ns = params_kw.copy()
id = params_kw.id
if not id or len(id) > 32:
id = uuid()
ns['id'] = id
db = DBPools()
async with db.sqlorContext('iptvdb') as sor:
r = await sor.C('iptvchannels', ns.copy())
return {
"widgettype":"Message",
"options":{
"user_data":ns,
"title":"Add Success",
"timeout":3,
"message":"ok"
}
}
return {
"widgettype":"Error",
"options":{
"title":"Add Error",
"timeout":3,
"message":"failed"
}
}

View File

@ -0,0 +1,26 @@
ns = {
'id':params_kw['id'],
}
db = DBPools()
async with db.sqlorContext('iptvdb') as sor:
r = await sor.D('iptvchannels', ns)
print('delete success');
return {
"widgettype":"Message",
"options":{
"title":"Delete Success",
"timeout":3,
"message":"ok"
}
}
print('Delete failed');
return {
"widgettype":"Error",
"options":{
"title":"Delete Error",
"timeout":3,
"message":"failed"
}
}

View File

@ -0,0 +1,93 @@
ns = params_kw.copy()
print(f'get_iptvchannels.dspy:{ns=}')
if not ns.get('page'):
ns['page'] = 1
if not ns.get('sort'):
ns['sort'] = 'tv_name'
filterjson = params_kw.get('data_filter')
if not filterjson:
fields = [ f['name'] for f in [
{
"name": "id",
"title": "\u7f16\u53f7",
"type": "str",
"length": 32
},
{
"name": "tv_group",
"title": "\u9891\u9053\u7ec4",
"type": "str",
"length": 500
},
{
"name": "tv_name",
"title": "\u9891\u9053\u540d\u79f0",
"type": "str",
"length": 500
},
{
"name": "logo_url",
"title": "\u53f0\u6807url",
"type": "str",
"length": 1000
},
{
"name": "url",
"title": "url",
"type": "str",
"length": 1000
},
{
"name": "media_type",
"title": "\u5a92\u4f53\u7c7b\u578b",
"type": "str",
"length": 100
},
{
"name": "download_date",
"title": "\u4e0b\u8f7d\u65e5\u671f",
"type": "str",
"length": 10
},
{
"name": "channel_delay",
"title": "\u9891\u9053\u5ef6\u8fdf",
"type": "short"
},
{
"name": "channel_grade",
"title": "\u9891\u9053\u7b49\u7ea7",
"type": "short"
},
{
"name": "del_flg",
"title": "\u5220\u9664\u6807\u5fd7",
"type": "str",
"length": 1
}
] ]
filterjson = default_filterjson(fields, ns)
sql = '''select * from iptvchannels where 1=1 {}'''
if filterjson:
dbf = DBFilter(filterjson)
conds = dbf.gen(ns)
if conds:
ns.update(dbf.consts)
sql = sql.format(' and ' + conds)
else:
sql = sql.format('')
print(f'{sql=}')
db = DBPools()
async with db.sqlorContext('iptvdb') as sor:
r = await sor.sqlPaging(sql, ns)
return r
return {
"total":0,
"rows":[]
}

View File

@ -0,0 +1,170 @@
{
"widgettype":"Tabular",
"options":{
"width":"100%",
"height":"100%",
"title":"IPTV频道清单",
"css":"card",
"editable":{
"new_data_url":"{{entire_url('add_iptvchannels.dspy')}}",
"delete_data_url":"{{entire_url('delete_iptvchannels.dspy')}}",
"update_data_url":"{{entire_url('update_iptvchannels.dspy')}}"
},
"data_url":"{{entire_url('./get_iptvchannels.dspy')}}",
"data_method":"GET",
"data_params":{{json.dumps(params_kw, indent=4)}},
"row_options":{
"browserfields": {
"exclouded": [
"id",
"media_type",
"download_date",
"channel_delay",
"channel_grade",
"del_flg",
"tv_group",
"logo_url",
"url"
],
"cwidth": {},
"alters": null
},
"editexclouded":[
"id"
],
"fields":[
{
"name": "id",
"title": "\u7f16\u53f7",
"type": "str",
"length": 32,
"cwidth": 18,
"uitype": "str",
"datatype": "str",
"label": "\u7f16\u53f7"
},
{
"name": "tv_group",
"title": "\u9891\u9053\u7ec4",
"type": "str",
"length": 500,
"cwidth": 18,
"uitype": "text",
"rows": 4,
"datatype": "str",
"label": "\u9891\u9053\u7ec4"
},
{
"name": "tv_name",
"title": "\u9891\u9053\u540d\u79f0",
"type": "str",
"length": 500,
"cwidth": 18,
"uitype": "text",
"rows": 4,
"datatype": "str",
"label": "\u9891\u9053\u540d\u79f0"
},
{
"name": "logo_url",
"title": "\u53f0\u6807url",
"type": "str",
"length": 1000,
"cwidth": 18,
"uitype": "text",
"rows": 4,
"datatype": "str",
"label": "\u53f0\u6807url"
},
{
"name": "url",
"title": "url",
"type": "str",
"length": 1000,
"cwidth": 18,
"uitype": "text",
"rows": 4,
"datatype": "str",
"label": "url"
},
{
"name": "media_type",
"title": "\u5a92\u4f53\u7c7b\u578b",
"type": "str",
"length": 100,
"cwidth": 18,
"uitype": "str",
"datatype": "str",
"label": "\u5a92\u4f53\u7c7b\u578b"
},
{
"name": "download_date",
"title": "\u4e0b\u8f7d\u65e5\u671f",
"type": "str",
"length": 0,
"cwidth": 10,
"uitype": "date",
"datatype": "str",
"label": "\u4e0b\u8f7d\u65e5\u671f"
},
{
"name": "channel_delay",
"title": "\u9891\u9053\u5ef6\u8fdf",
"type": "short",
"length": 0,
"uitype": "int",
"datatype": "short",
"label": "\u9891\u9053\u5ef6\u8fdf"
},
{
"name": "channel_grade",
"title": "\u9891\u9053\u7b49\u7ea7",
"type": "short",
"length": 0,
"uitype": "int",
"datatype": "short",
"label": "\u9891\u9053\u7b49\u7ea7"
},
{
"name": "del_flg",
"title": "\u5220\u9664\u6807\u5fd7",
"type": "str",
"length": 1,
"cwidth": 4,
"uitype": "str",
"datatype": "str",
"label": "\u5220\u9664\u6807\u5fd7"
}
]
},
"content_view":{
"widgettype": "urlwidget",
"options": {
"params": {
"channelid": "${id}"
},
"url": "{{entire_url('..\/taging')}}"
}
},
"page_rows":160,
"cache_limit":5
}
}

View File

@ -0,0 +1,24 @@
ns = params_kw.copy()
db = DBPools()
async with db.sqlorContext('iptvdb') as sor:
r = await sor.U('iptvchannels', ns)
print('update success');
return {
"widgettype":"Message",
"options":{
"title":"Update Success",
"timeout":3,
"message":"ok"
}
}
print('update failed');
return {
"widgettype":"Error",
"options":{
"title":"Update Error",
"timeout":3,
"message":"failed"
}
}

6
wwwroot/keypress.ui Normal file
View File

@ -0,0 +1,6 @@
{
"widgettype":"KeyPress",
"options":{
"height":"100%"
}
}

30
wwwroot/login.ui Normal file
View File

@ -0,0 +1,30 @@
{
"widgettype":"PopupWindow",
"options":{
"archor":"cc",
"auto_open":true,
"title":"登录",
"width":"80%",
"height":"80%"
},
"subwidgets":[
{
"widgettype":"Form",
"options":{
"cols":1,
"fields":[
{
"name":"username",
"label":"用户名",
"uitype":"str"
},
{
"name":"password",
"label":"密码",
"uitype":"password"
}
]
}
}
]
}

13473
wwwroot/m3u/A.m3u Normal file

File diff suppressed because it is too large Load Diff

1066
wwwroot/m3u/boxTV.m3u Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

390
wwwroot/m3u/taiwan.m3u Normal file
View File

@ -0,0 +1,390 @@
三立台灣[1920*1080],https://setlive-lh.akamaihd.net/i/settaiwan_1@301196/index_1080_av-b.m3u8?sd=10&rebase=on
三立都會[1920*1080],https://setlive-lh.akamaihd.net/i/setmetro_1@132201/index_1080_av-b.m3u8?sd=10&rebase=on
三立台湾[1920*1080],https://setlive-lh.akamaihd.net/i/settaiwan_1@301196/index_1080_av-b.m3u8?sd=10&rebase=on
三立都会[1920*1080],https://setlive-lh.akamaihd.net/i/setmetro_1@132201/index_1080_av-b.m3u8?sd=10&rebase=on
三立台灣台,p8p://fccs.123178.top:9906/60435a1000013bcc070a9c3b0ad870c7.ts
三立都會台,p8p://fccs.123178.top:9906/60435aa10002e65e070cd311539826d8.ts
三立台湾,https://setlive-lh.akamaihd.net/i/settaiwan_1@301196/index_1080_av-b.m3u8?sd=10&rebase=on
三立都会,https://setlive-lh.akamaihd.net/i/setmetro_1@132201/index_1080_av-b.m3u8?sd=10&rebase=on
民视[720*404],rtmp://59.124.75.153/sat/tv052
华视[720*404],rtmp://59.124.75.153/sat/tv112
华视[720*404],http://lytcyy.qcytv.top/wz7.php?id=30
民视[1280*720],http://lytcyy.qcytv.top/wz7.php?id=24
民视[1280*720],rtmp://59.124.75.153/sat/tv051
台视[1280*720],rtmp://59.124.75.153/sat/tv071
中视[1280*720],rtmp://59.124.75.153/sat/tv091
华视[1280*720],rtmp://59.124.75.153/sat/tv111
TVBS欢乐台[1280*720],rtmp://59.124.75.153/sat/tv421
TVBS欢乐台[1280*720],rtmp://59.124.75.153:1935/sat/tv421
TVBS新闻台[1280*720],rtmp://59.124.75.153/sat/tv551
TVBS新闻台[1280*720],rtmp://59.124.75.153:1935/sat/tv551
民视[1280*720],rtmp://161.202.204.248:1935/sat/tv051
台视[1280*720],rtmp://161.202.204.248/sat/tv071
台视[1280*720],rtmp://161.202.204.248:1935/sat/tv071
中视[1280*720],rtmp://161.202.204.248/sat/tv091
中视[1280*720],rtmp://161.202.204.248:1935/sat/tv091
華视[1280*720],rtmp://161.202.204.248:1935/sat/tv111
华视[1280*720],rtmp://161.202.204.248/sat/tv111
民视[1280*720],rtmp://161.202.204.248/sat/tv051
TVBS新闻台[1280*720],rtmp://161.202.204.248:1935/sat/tv551
TVBS欢乐台[1280*720],rtmp://161.202.204.248:1935/sat/tv421
TVBS欢乐台[1280*720],rtmp://161.202.204.248/sat/tv421
东森超视[1280*720],rtmp://161.202.204.248:1935/sat/tv771
东森超视[1280*720],rtmp://161.202.204.248/sat/tv771
东森财经新闻[1280*720],rtmp://161.202.204.248:1935/sat/tv571
华视[720*404],rtmp://161.202.204.248/sat/tv112
民视[720*404],rtmp://161.202.204.248/sat/tv052
TVBS新闻台[720*408],rtmp://161.202.204.248/sat/tv552
TVBS欢乐台[720*408],rtmp://161.202.204.248/sat/tv422
中视[720*404],rtmp://161.202.204.248/sat/tv092
台视[720*404],rtmp://161.202.204.248/sat/tv072
东森财经[720*404],rtmp://161.202.204.248:1935/sat/tv572
民視新聞,p8p:// 45.92.126.18:9906/604350c30004f22006e648675a9482b5.ts
三立新聞,p8p:// 45.92.126.18:9906/604351bb000723c406ea11b7e2f757c8.ts
台視新聞,p8p:// 45.92.126.18:9906/60448580000cd93c01bc61c5ce37b60a.ts
東森新聞,http://seb.sason.top/sc/dsxw_fhd.m3u8
東森財經新聞,http://seb.sason.top/sc/dscjxw_fhd.m3u8
年代新闻[1920*1080],http://107.167.5.66/mylive/102/2050/index.m3u8
台視新聞,http://seb.sason.top/sc/tsxw_fhd.m3u8
CTI中天新聞HD,http://seb.sason.top/sc/ztxw_fhd.m3u8
中视,rtmp://161.202.204.248/sat/tv091
华视,rtmp://161.202.204.248/sat/tv112
台视,rtmp://161.202.204.248/sat/tv071
民视,rtmp://161.202.204.248/sat/tv052
TVBS·欢乐台,rtmp://161.202.204.248/sat/tv422
TVBS·新闻台,rtmp://161.202.204.248/sat/tv552
东森财经新闻,rtmp://161.202.204.248:1935/sat/tv571
MoMo综合台,rtmp://161.202.204.248/sat/tv761
TVBS欢乐,rtmp://161.202.204.248:1935/sat/tv421
TVBS新闻,rtmp://161.202.204.248:1935/sat/tv551
寰宇新聞二台,p8p:// 45.92.126.18:9906/60434c6b000d588a06d552cd4d7910ec.ts
年代新聞,p8p:// 45.92.126.18:9906/60434d73000091e406d956c8607013df.ts
台視 HD,p8p://fccs.123178.top:9906/604483a00001a70f01b50be75415ab3a.ts
公視 HD,p8p://fccs.123178.top:9906/60448ebb000b822801e06fe5cbe82807.ts
台視綜合,p8p://fccs.123178.top:9906/6044936700021fe101f2ad5ea50e836e.ts
中天綜合,p8p://fccs.123178.top:9906/60449782000897640202b87e04b40c6d.ts
中天亞洲,p8p://fccs.123178.top:9906/60449a27000cf419020d0e24d4fdafd9.ts
TVBS歡樂台,p8p://fccs.123178.top:9906/60449be700025e680213e16e7d39f5a6.ts
三立台湾,https://setlive-lh.akamaihd.net/i/settaiwan_1@301196/index_1080_av-b.m3u8?sd=10&rebase=on
三立台湾,http://lytcyy.qcytv.top/wz7.php?id=129
三立台湾,https://setlive-lh.akamaihd.net/i/settaiwan_1@301196/index_1080_av-b.m3u8?sd=10&rebase=on
寰宇新聞台,p8p://fccs.123178.top:9906/60434bdc0009a41d06d32342bef082c3
寰宇新聞二台,p8p://fccs.123178.top:9906/60434c6b000d588a06d552cd4d7910ec
東森電影台,p8p://fccs.123178.top:9906/60449ece0009c6ea021f39ac30bce072
民視新聞,p8p://fccs.123178.top:9906/604350c30004f22006e648675a9482b5.ts
三立新聞,p8p://fccs.123178.top:9906/604351bb000723c406ea11b7e2f757c8.ts
TVBS,p8p://fccs.123178.top:9906/60435407000d43d906f30c28a0b64eda.ts
非凡新聞,p8p://fccs.123178.top:9906/6044966b0006d57a01fe7633c96a5506.ts
三立財經,p8p://fccs.123178.top:9906/604496f8000b3b7b02009e1b5871dd53.ts
三立都会[1920*1080],https://setlive-lh.akamaihd.net/i/setmetro_1@132201/index_1080_av-b.m3u8?sd=10&rebase=on
中视,rtmp://161.202.204.248/sat/tv091
中视,rtmp://59.124.75.130/sat/tv091
中视[1280*720],http://lytcyy.qcytv.top/wz7.php?id=29
华视,rtmp://161.202.204.248/sat/tv112
华视,rtmp://59.124.75.130/sat/tv112
台视,rtmp://161.202.204.248/sat/tv071
台视,rtmp://59.124.75.130/sat/tv071
民视,rtmp://161.202.204.248/sat/tv052
民视,rtmp://59.124.75.130/sat/tv052
民視 HD,p8p://fccs.123178.top:9906/6043597b000602c20708576dff009975.ts
TVBS·欢乐台,rtmp://161.202.204.248/sat/tv422
TVBS·欢乐台,rtmp://161.202.204.248/sat/tv421
TVBS·新闻台,rtmp://161.202.204.248/sat/tv552
TVBS·新闻台,rtmp://161.202.204.248/sat/tv551
中天新闻,http://www.hrpan.tk/hls/tl_ztxw.m3u8
寰宇新闻,http://www.hrpan.tk/hls/tl_hyxw.m3u8
亚洲新闻[1280*720],http://d2e1asnsl7br7b.cloudfront.net/7782e205e72f43aeb4a48ec97f66ebbe/index_4.m3u8
三立台湾,http://lytcyy.qcytv.top/wz7.php?id=129
三立都会,https://setlive-lh.akamaihd.net/i/setmetro_1@132201/index_1080_av-b.m3u8?sd=10&rebase=on
三立台湾,https://setlive-lh.akamaihd.net/i/settaiwan_1@301196/index_1080_av-b.m3u8?sd=10&rebase=on
三立都會,https://setlive-lh.akamaihd.net/i/setmetro_1@132201/index_1080_av-b.m3u8?sd=10&rebase=on
三立台灣,https://setlive-lh.akamaihd.net/i/settaiwan_1@301196/index_1080_av-b.m3u8?sd=10&rebase=on
三立都会,http://lytcyy.qcytv.top/wz7.php?id=131
華視 HD,p8p://fccs.123178.top:9906/60448a5e0007261101cf6380c974fa71.ts
中視 HD,p8p://fccs.123178.top:9906/60448622000d89b401bedac2a3be746c.ts
台視 HD,p8p://fccs.123178.top:9906/604483a00001a70f01b50be75415ab3a.ts
民視 HD,p8p://fccs.123178.top:9906/6043597b000602c20708576dff009975.ts
中視經典台,p8p://fccs.123178.top:9906/604489250001a93601ca9b70388b5d75.ts
公視 HD,p8p://fccs.123178.top:9906/60448ebb000b822801e06fe5cbe82807.ts
公視3HD,p8p://fccs.123178.top:9906/6044903d0009037901e653127d757c7b.ts
東森戲劇,p8p://fccs.123178.top:9906/60449e3500031323021ce24de00b3ef2.ts
龍華電影,p8p://fccs.123178.top:9906/604426fa000c13eb004b26236e73affa.ts
寰宇新聞台,p8p://fccs.123178.top:9906/60434bdc0009a41d06d32342bef082c3.ts
TVB星河,p8p://fccs.123178.top:9906/60463cd5000f308a087086672166e0af.ts
TVBS,p8p://fccs.123178.top:9906/60435407000d43d906f30c28a0b64eda
年代MUCH,p8p://fccs.123178.top:9906/60449ce00006c4040217af361b6c5a1a.ts
中視新聞,p8p://fccs.123178.top:9906/604487e700053cde01c5c22abcaf0467.ts
TVBS新聞,p8p://fccs.123178.top:9906/6075902e00016792114a73588fb745ba
三立新聞,p8p://fccs.123178.top:9906/604351bb000723c406ea11b7e2f757c8
東森新聞,p8p://fccs.123178.top:9906/60e382fe000d9e21042519ca9bf23e95
民視新聞,p8p://fccs.123178.top:9906/604350c30004f22006e648675a9482b5
TVBS新闻台[1280*720],http://lytcyy.qcytv.top/wz7.php?id=42
三立台湾[1920*1080],http://lytcyy.qcytv.top/wz7.php?id=129
三立都会[1920*1080],http://lytcyy.qcytv.top/wz7.php?id=131
年代新闻,http://107.167.5.66:80/mylive/102/2050/index.m3u8
非凡新闻,http://107.167.5.66:80/mylive/102/2058/index.m3u8
港台电视RTHK-TV-31,https://cdn.hkdtmb.com/hls/31/index.m3u8
港台电视RTHK-TV-32,https://cdn.hkdtmb.com/hls/32/index.m3u8
大爱海外,https://pulltv3.wanfudaluye.com/live/tv3.m3u8
大爱2台,https://pulltv2.wanfudaluye.com/live/tv2.m3u8
大爱2台,https://pulltv1.wanfudaluye.com/live/tv2.m3u8
大爱1台,https://pulltv1.wanfudaluye.com/live/tv1.m3u8
双星,http://50.7.161.82:8278/streams/d/Shuangxing/playlist.m3u8
全佳,http://50.7.161.82:8278/streams/d/Quanjia/playlist.m3u8
HBO台湾,http://198.16.106.62:8278/streams/d/sundance_twn/playlist.m3u8
nhk华语,https://nhkw-zh-hlscomp.akamaized.net/ixxemlzk1vqvy44o/playlist.m3u8
東森洋片台,p8p://fccs.123178.top:9906/60449f6d000c10680221a75af38e252f
高點綜合,p8p://fccs.123178.top:9906/604640070003e1f8087cfed268004b6c
愛爾達綜合台,p8p://fccs.123178.top:9906/60689fa0000c9dae134f712965a8f823.ts
愛爾達綜合台,p8p://fccs.123178.top:9906/60689fa0000c9dae134f712965a8f823
愛爾達影劇台,p8p://fccs.123178.top:9906/6044382f0001bdea008e5a851f8cf009.ts
愛爾達影劇台,p8p://fccs.123178.top:9906/6044382f0001bdea008e5a851f8cf009
采昌影劇台,p8p://fccs.123178.top:9906/604411ec0004d59109d8d087e9645ce6
EYETV戲劇,p8p://fccs.123178.top:9906/60442b6d000654ae005c85e289945252
EYETV戲劇,p8p://fccs.123178.top:9906/60442b6d000654ae005c85e289945252.ts
星衛娛樂台,p8p://fccs.123178.top:9906/6044229300000d0a0039f0b6a59d1511.ts
愛爾達體育2台,p8p://fccs.123178.top:9906/60443b320005c061009a1f44d1793932.ts
歷史頻道,p8p://fccs.123178.top:9906/6049468f0008dae6144e835756f6d068.ts
BBC Lifestyle,p8p://fccs.123178.top:9906/604403fd0002ca1a09a262690b80ac95.ts
BBC Earth,p8p://fccs.123178.top:9906/6044049e000eb7a609a4da5fcd30cc43.ts
EYE TV旅遊台,p8p://fccs.123178.top:9906/60494553000b340f1449b191f22032d6.ts
TLC旅遊台,p8p://fccs.123178.top:9906/60440517000a918709a6b1f73be1eeb9.ts
亞洲旅遊,p8p://fccs.123178.top:9906/604405c80008412109a964c89ca82891.ts
亞洲美食HD,p8p://fccs.123178.top:9906/6044065f0003bace09abb177a024828d.ts
華視教育,p8p://fccs.123178.top:9906/60448d730005f21d01db6d390ab97993.ts
東森財經,p8p://fccs.123178.top:9906/60435ba7000123740710d20d0fa4a082.ts
東森財經,p8p://fccs.123178.top:9906/60435ba7000123740710d20d0fa4a082
野生動物,p8p://fccs.123178.top:9906/604401050005fe790996ca7b4ed24991
動物星球,p8p://fccs.123178.top:9906/60440362000e75bc09a007eeaa0519c7
龍華洋片台,p8p://fccs.123178.top:9906/6044287d000e2bb500510e64fec426ab
龍華電影台,p8p://fccs.123178.top:9906/604426fa000c13eb004b26236e73affa
龍華戲劇台,p8p://fccs.123178.top:9906/60442a110002751300573584bb335a71
龍華影劇,p8p://fccs.123178.top:9906/604347a3000cc1fe06c2a567b371c0d6
龍華影劇台,p8p://fccs.123178.top:9906/60441771000d4807000e774ad2f62e16
龍華偶像台,p8p://fccs.123178.top:9906/60442ac30006b54f0059edebe8733672
衛視西片台,p8p://fccs.123178.top:9906/604416620003377d000a521e160e3141
好萊塢電影,p8p://fccs.123178.top:9906/6044d78800021f9602fcce46b541cf65
KIX電影台,p8p://fccs.123178.top:9906/6044145c000e8fb900026d95dbb7683a
FOX 頻道,p8p://fccs.123178.top:9906/60440eb10006690c09cc32777254e90a
FOX動作台,p8p://fccs.123178.top:9906/60440fd1000e6f3b09d0998515d1967d
FOX優質電影台,p8p://fccs.123178.top:9906/60441060000dae1309d2c7eb236de319
FOX福斯電影台,p8p://fccs.123178.top:9906/60693d0e000cf43215b666ef7701d76e
Fox福斯家庭,p8p://fccs.123178.top:9906/6044114c0004d19e09d65f86a75bad6b
HBO HD,p8p://fccs.123178.top:9906/604338a40001163206880e5297cc95ab
華納電影台,p8p://fccs.123178.top:9906/604414f400055b780004bcfa6ee82d22
天映電影台,p8p://fccs.123178.top:9906/60441c660009af940021d366383a86ea
星衛HD電影,p8p://fccs.123178.top:9906/6044d33b0006a70302ec02a7d10a2600
龍祥電影台,p8p://fccs.123178.top:9906/6045bb31000469b906761b04cfa6bdb1
年代新聞,p8p://fccs.123178.top:9906/60434d73000091e406d956c8607013df.ts
靖天育樂,p8p://fccs.123178.top:9906/60469f430002fd3e09f100f732da02a0.ts
緯來體育HD,p8p://fccs.123178.top:9906/6044a3c3000d96e6023297aef85769a2.ts
衛視電影台,p8p://fccs.123178.top:9906/6044d33b0006a70302ec02a7d10a2600.ts
國興衛視,p8p://fccs.123178.top:9906/6044d406000399b302ef1ad77f59ca13.ts
JET综合,p8p://fccs.123178.top:9906/6044d49a0003828802f15cf1eb31478a.ts
八大戲劇台,p8p://fccs.123178.top:9906/6044d5ac000936f902f58cb70525846f.ts
八大綜合,p8p://fccs.123178.top:9906/6044d641000e5dc002f7d411a124e035.ts
八大娛樂台,p8p://fccs.123178.top:9906/6044d70900008dea02faddc78bf8a126.ts
好萊塢電影,p8p://fccs.123178.top:9906/6044d78800021f9602fcce46b541cf65.ts
Cinemax,p8p://fccs.123178.top:9906/60463f7d000802da087ae4d0305dfcaf.ts
龍祥電影台,p8p://fccs.123178.top:9906/6045bb31000469b906761b04cfa6bdb1.ts
衛視中文台,p8p://fccs.123178.top:9906/6045bbb2000922ef0678142229e89274.ts
高點綜合,p8p://fccs.123178.top:9906/604640070003e1f8087cfed268004b6c.ts
生命電視台,p8p://fccs.123178.top:9906/60463d9a0001f1630873848a76accc36.ts
華藏衛視,p8p://fccs.123178.top:9906/60463e4f0004c7480876484c7d16a8e0.ts
CNN Internationa,p8p://fccs.123178.top:9906/604641f8000e2252088496d9f8a5ad44.ts
BBC WORLD NEWS,p8p://fccs.123178.top:9906/60464299000eba8708870be862b68160.ts
纬来体育,rtmp://161.202.204.248/sat/tv721
纬来体育,rtmp://59.124.75.130/sat/tv721
纬来体育,rtmp://59.124.75.130:1935/sat/tv721
纬来育乐,rtmp://161.202.204.248/sat/tv701
纬来育乐,rtmp://59.124.75.130/sat/tv702
纬来育乐,rtmp://59.124.75.130:1935/sat/tv701
纬来育乐,rtmp://59.124.75.130/sat/tv701
纬来育乐,rtmp://59.124.75.157/sat/tv701
东森超视,rtmp://161.202.204.248/sat/tv772
东森超视,rtmp://59.124.75.130/sat/tv772
东森超视,rtmp://59.124.75.130:1935/sat/tv771
东森超视,rtmp://59.124.75.130/sat/tv771
博斯魅力,rtmp://161.202.204.248/sat/md042
博斯魅力,rtmp://59.124.75.130/sat/md042
东森财经新闻,rtmp://161.202.204.248:1935/sat/tv571
FOX体育,rtmp://161.202.204.248:1935/sat/tv731
大爱一台[1280*720],https://pulltv1.wanfudaluye.com/live/tv1.m3u8
大爱二台[1280*720],https://pulltv2.wanfudaluye.com/live/tv2.m3u8
大爱二台[1280*720],https://pulltv1.wanfudaluye.com/live/tv2.m3u8
大爱三台[1280*720],https://pulltv3.wanfudaluye.com/live/tv3.m3u8
大愛海外[1280*720],https://pulltv3.wanfudaluye.com/live/tv3.m3u8
八大娱乐 GTV Entertainment[1280*720],http://198.16.106.62:8278/streams/d/badaentertain/playlist.m3u8
国家地理,https://livecdn.fptplay.net/foxlive/natgeohd_hls.smil/chunklist_b2500000.m3u8
国家地理,http://185.180.221.194:8278/streams/d/Natgeo/playlist.m3u8
TVBSHD,http://www.hrpan.tk/hls/tvbspd.m3u8
東森戲劇,p8p://fccs.123178.top:9906/60449e3500031323021ce24de00b3ef2.ts
緯來日本台,p8p://fccs.123178.top:9906/6044a02c000bf3c30224916a373cdb2c.ts
人間衛視,p8p://fccs.123178.top:9906/60463f7d000802da087ae4d0305dfcaf.ts
BS釣りビジョン,p8p://fccs.123178.top:9906/604402870001f71c099cad43e96233b3.ts
LUXE奢華頻道,p8p://fccs.123178.top:9906/60689d7b000b57f61347104e33aa1e24.ts
afc亞洲美食 HD,p8p://fccs.123178.top:9906/6044065f0003bace09abb177a024828d.ts
罪案偵緝頻道,p8p://fccs.123178.top:9906/604947cc00047a751453588132b90a12.ts
華納Warner TV,p8p://fccs.123178.top:9906/604414f400055b780004bcfa6ee82d22.ts
CinemaWorld,p8p://fccs.123178.top:9906/604415aa00054259000783e434297e54.ts
衛視西片,p8p://fccs.123178.top:9906/604416620003377d000a521e160e3141.ts
BLUE ANT EXTREME,p8p://fccs.123178.top:9906/60441771000d4807000e774ad2f62e16.ts
好萊塢電影,p8p://fccs.123178.top:9906/6044d78800021f9602fcce46b541cf65.ts
EYETV戲劇,p8p://fccs.123178.top:9906/60442b6d000654ae005c85e289945252.ts
有线电影,http://93.190.139.36:8278/streams/d/hk03_twn/playlist.m3u8
HBO台1,http://107.167.5.66:80/mylive/102/2065/index.m3u8
HBO GO,http://107.167.5.66/mylive/102/2070/index.m3u8
HBO,http://107.167.5.66/mylive/102/2065/index.m3u8
华城影视,http://live1.nty.tv189.com/tm-cridyty-800k.m3u8?sign=&guid=&uid=
东森电影,http://107.167.5.66/mylive/102/2062/index.m3u8
東森電影台,p8p://fccs.123178.top:9906/60449ece0009c6ea021f39ac30bce072.ts
纬来电影,http://107.167.5.66/mylive/102/2063/index.m3u8
衛视电影,http://107.167.5.66/mylive/102/2061/index.m3u8
HBO,http://107.167.5.66/mylive/102/2065/index.m3u8
龍祥时代,http://107.167.5.66/mylive/102/2064/index.m3u8
衛視西片,p8p://45.92.126.18:9906/604416620003377d000a521e160e3141.ts
天映频道,http://50.7.161.82:8278/streams/d/Celestial/playlist.m3u8
天映经典,http://50.7.161.82:8278/streams/d/Celestial2/playlist.m3u8
天映電影,p8p://fccs.123178.top:9906/60441c660009af940021d366383a86ea.ts
八大娛樂台,p8p://fccs.123178.top:9906/6044d70900008dea02faddc78bf8a126.ts
八大綜合,p8p://fccs.123178.top:9906/6044d641000e5dc002f7d411a124e035.ts
八大戲劇台,p8p://fccs.123178.top:9906/6044d5ac000936f902f58cb70525846f.ts
東森戲劇,p8p://fccs.123178.top:9906/60449e3500031323021ce24de00b3ef2.ts
天映电影,http://50.7.161.82:8278/streams/d/Celestial/playlist.m3u8
經典電影台,http://103.140.229.13/BOBO/bibi.php?id=23285297
經典影視台,http://103.140.229.13/BOBO/bibi.php?id=23169468
經典功夫台,http://103.140.229.13/BOBO/bibi.php?id=21715386
經典電影台,http://103.140.229.13/BOBO/bibi.php?id=23285297
纬来体育,rtmp://161.202.204.248/sat/tv721
纬来育乐,rtmp://161.202.204.248/sat/tv701
纬来日本,rtmp://161.202.204.248:1935/sat/tv521
爱尔达体育一,rtmp://161.202.204.248/sat/md011
东森超视,rtmp://161.202.204.248/sat/tv772
博斯魅力,rtmp://161.202.204.248/sat/md042
Mono综合,rtmp://161.202.204.248:1935/sat/tv761
FOX体育,rtmp://161.202.204.248:1935/sat/tv731
FOX2体育,rtmp://161.202.204.248:1935/sat/tv741
TVBS新聞,rtmp://161.202.204.248/sat/tv551
FOX体育3,rtmp://161.202.204.248:1935/sat/md031
HBO-HD,http://107.167.5.66:80/mylive/102/2065/index.m3u8
HBO-HD,http://198.16.106.62:8278/streams/d/sundance_twn/playlist.m3u8
HBO-HD,p8p://fccs.123178.top:9906/604338a40001163206880e5297cc95ab
FOXMOVIES,http://60.251.59.179:8504/xoxo.m3u8
FOXMOVIES,http://60.251.59.179:8543/xoxo.m3u8
FOXMOVIES,http://60.251.59.179:8506/xoxo.m3u8
FOX-HD,p8p://fccs.123178.top:9906/60441060000dae1309d2c7eb236de319.ts
衛視西片,p8p://fccs.123178.top:9906/604416620003377d000a521e160e3141.ts
香港福斯電影,p8p://fccs.123178.top:9906/60693d0e000cf43215b666ef7701d76e.ts
罪案偵緝頻道,p8p://fccs.123178.top:9906/604947cc00047a751453588132b90a12.ts
星衛電影 HD,p8p://fccs.123178.top:9906/6044d33b0006a70302ec02a7d10a2600.ts
星衛娛樂台,p8p://fccs.123178.top:9906/6044229300000d0a0039f0b6a59d1511.ts
天映电影,http://50.7.161.82:8277/streams/d/celestial_pye/playlist.m3u8
天映经典,http://50.7.161.82:8278/streams/d/Celestial2/playlist.m3u8
FOX-台湾,http://60.251.59.179:8506/xoxo.m3u8
美食星球[1280*720],http://lytcyy.qcytv.top/wz7.php?id=102
龍翔電影台[1920*1080],http://107.167.5.66:80/mylive/102/2064/index.m3u8
東森电影台[1920*1080],http://107.167.5.66:80/mylive/102/2062/index.m3u8
纬来电影HD[1920*1080],http://107.167.5.66:80/mylive/102/2063/index.m3u8
卫视电影台[1920*1080],http://107.167.5.66:80/mylive/102/2061/index.m3u8
纬来电影[1920*1080],http://107.167.5.66/mylive/102/2063/index.m3u8
HBO[1920*1080],http://107.167.5.66/mylive/102/2065/index.m3u8
HBO GO[1920*1080],http://107.167.5.66/mylive/102/2070/index.m3u8
HBO台1[1920*1080],http://107.167.5.66:80/mylive/102/2065/index.m3u8
时尚频道[1920*1080],http://juyunlive.juyun.tv/live/24950198.m3u8
亚洲新闻[1920*1080],https://d2e1asnsl7br7b.cloudfront.net/7782e205e72f43aeb4a48ec97f66ebbe/index_5.m3u8
HBO台湾[1920*1080],http://198.16.106.62:8278/streams/d/sundance_twn/playlist.m3u8
高清时尚[1920*1080],http://95.67.47.115/hls/hdfashion_ua_hi/index.m3u8
亚洲新闻台(CNA)[1920*1080],https://d2e1asnsl7br7b.cloudfront.net/7782e205e72f43aeb4a48ec97f66ebbe/index_5.m3u8
NOW新闻[1920*1080],http://iptv5.phoves.com.cn/mytv/hodtv.php?id=18
国家地理野生频道[1920*1080],http://46.149.191.219:9109/play/a005
TV-6740[1920*1080],http://slive.ytn.co.kr/ytn/_definst_/ytn_stream_20190306/playlist.m3u8
东森超视[1280*720],rtmp://59.124.75.153/sat/tv771
东森超视[1280*720],rtmp://59.124.75.153:1935/sat/tv771
东森财经新闻[1280*720],rtmp://59.124.75.153:1935/sat/tv571
纬来日本[1280*720],rtmp://59.124.75.153:1935/sat/tv521
纬来育乐[1280*720],rtmp://59.124.75.153/sat/tv701
纬来育乐[1280*720],rtmp://59.124.75.153:1935/sat/tv701
纬来体育[1280*720],rtmp://59.124.75.153/sat/tv721
纬来体育[1280*720],rtmp://59.124.75.153:1935/sat/tv721
FOX体育[1280*720],rtmp://59.124.75.153:1935/sat/tv731
FOX2体育[1280*720],rtmp://59.124.75.153:1935/sat/tv741
MoMo综合台[1280*720],rtmp://59.124.75.153/sat/tv761
Mono综合[1280*720],rtmp://59.124.75.153:1935/sat/tv761
博斯运动1,[1280*720],rtmp://59.124.75.153:1935/sat/md041
ELEVEN2体育[1280*720],rtmp://59.124.75.153/sat/md051
天映电影[1280*720],http://50.7.161.82:8278/streams/d/Celestial/playlist.m3u8
动物星球[1280*720],http://50.7.161.82:8278/streams/d/AnimalPlanet/playlist.m3u8
博斯魅力[1280*720],rtmp://161.202.204.248/sat/md041
纬来体育[1280*720],rtmp://161.202.204.248/sat/tv721
纬来体育[1280*720],rtmp://161.202.204.248:1935/sat/tv721
纬来育乐[1280*720],rtmp://161.202.204.248/sat/tv701
纬来育乐[1280*720],rtmp://161.202.204.248:1935/sat/tv701
纬来日本[1280*720],rtmp://161.202.204.248:1935/sat/tv521
博斯運動 II[1280*720],rtmp://161.202.204.248:1935/sat/md051
MoMo综合台[1280*720],rtmp://161.202.204.248/sat/tv761
Mono综合[1280*720],rtmp://161.202.204.248:1935/sat/tv761
FOX体育[1280*720],rtmp://161.202.204.248:1935/sat/tv731
FOX2体育[1280*720],rtmp://161.202.204.248:1935/sat/tv741
TVBS新聞[1280*720],rtmp://161.202.204.248/sat/tv551
ELTA1台[1280*720],rtmp://161.202.204.248:1935/sat/md041
TCL[1280*720],http://60.251.59.179:8504/xoxo.m3u8
东森YOYO[1280*720],http://60.251.59.179:8506/xoxo.m3u8
纬来电影[1280*720],http://60.251.59.179:8543/xoxo.m3u8
亚洲新闻[1280*720],http://d2e1asnsl7br7b.cloudfront.net/7782e205e72f43aeb4a48ec97f66ebbe/index_4.m3u8
大爱一台[1280*720],https://pulltv1.wanfudaluye.com/live/tv1.m3u8
大爱二台[1280*720],https://pulltv2.wanfudaluye.com/live/tv2.m3u8
大爱三台[1280*720],https://pulltv3.wanfudaluye.com/live/tv3.m3u8
大爱二台[1280*720],https://pulltv1.wanfudaluye.com/live/tv2.m3u8
大愛海外[1280*720],https://pulltv3.wanfudaluye.com/live/tv3.m3u8
亚洲美食[1280*720],http://198.16.106.62:8278/streams/d/asiafood_zero/playlist.m3u8
美食星球[1280*720],http://198.16.106.62:8278/streams/d/foodplanet_zero/playlist.m3u8
HBO原創電影[1280*720],http://198.16.106.62:8278/streams/d/hbosignature_zero/playlist.m3u8
TVB剧场[1280*720],http://39.134.216.5/live.hcs.cmvideo.cn:8088/wd_r4/virtuallive/5101059662/150/index.m3u8?&encrypt=1
華藏衛視[1280*720],http://118.163.88.61:1935/hwazanlivetv/live.stream/playlist.m3u8
法国第五世界台FHF[1920*1080],http://v3plusinfo247hls-i.akamaihd.net/hls/live/218877-b/v3plusinfo247hls/v3plusinfo247hls_1_1.m3u8
AFC-美食[1280*720],https://livecdn.fptplay.net/world/afchd_hls.smil/chunklist_b2500000.m3u8
索尼动画[1280*720],https://livecdn.fptplay.net/hda3/animaxport_2000.stream/.m3u8
BBCEarth[1280*720],http://198.16.106.62:8278/streams/d/bbcearthhd_zero/playlist.m3u8
原住民電視[1280*720],http://streamipcf.akamaized.net/live/_definst_/live_720/key_b1500.m3u8
天映经典[960*540],http://50.7.161.82:8278/streams/d/Celestial2/playlist.m3u8
纬来育乐[720*404],rtmp://161.202.204.248/sat/tv702
纬来日本[720*404],rtmp://161.202.204.248/sat/tv522
博斯魅力[720*408],rtmp://161.202.204.248/sat/md042
爱尔达体育一[1280*720],rtmp://161.202.204.248/sat/md011
FOX3[1280*720],rtmp://161.202.204.248:1935/sat/md021
爱尔达体育二[1280*720],rtmp://59.124.75.153/sat/md011
爱尔达体育一[1280*720],rtmp://59.124.75.153/sat/md021
爱尔体育[1280*720],rtmp://161.202.204.248:1935/sat/md011
国度新闻[854*480],https://vod.streamingfast.net/hls-vod/video/1200k/NW1A0180_1200k.mp4.m3u8
唯心电视[854*480],https://mobile.ccdntech.com/transcoder/_definst_/vod164_Live/live/playlist.m3u8
唯心电视[854*480],http://mobile.ccdntech.com/transcoder/_definst_/vod164_Live/live/chunklist_w1177047531.m3u8
MoMo台[720*404],rtmp://161.202.204.248/sat/tv762
爱尔达体育1[1280*720],rtmp://161.202.204.248/sat/md051
八大娱乐 GTV Entertainment[1280*720],http://198.16.106.62:8278/streams/d/badaentertain/playlist.m3u8
TVBL[1280*720],https://edge6a.v2h-cdn.com/RE_HD/TVB_HD.stream_720p/playlist.m3u8
CNN新闻[1280*720],http://live.cnnindonesia.com/livecnn/smil:cnntv.smil/chunklist_w1285822120_b384000_sleng.m3u8
CNN LIVE[1280*720],https://cnn-cnninternational-1-de.samsung.wurl.com/manifest/playlist_1280x720_3000k.m3u8
CNN LIVE[1280*720],https://cnn-cnninternational-1-gb.samsung.wurl.com/manifest/playlist_1280x720_3000k.m3u8
天映经典[960*540],http://50.7.161.82:8277/streams/d/celestial2_pye/playlist.m3u8
法国时尚[800*453],http://lb.streaming.sk/fashiontv/stream/chunklist_w1702070444.m3u8
中国环球电视[1024*576],http://live.cgtn.com/500/prog_index.m3u8
爱尔达体育1台[1280*720],rtmp://59.124.75.153/sat/md041
HBO中文[785*576],http://218.202.220.2:5000/nn_live.m3u8?id=HBO
好消息电视台1[854*480],http://live-350k.streamingfast.net/hls-live/goodtv/_definst_/liveevent/live-ch1-1.m3u8
好消息电视台2[854*480],http://live-350k.streamingfast.net/hls-live/goodtv/_definst_/liveevent/live-ch2-1.m3u8
Newtv精品电影[1920*1080],http://183.207.249.14/PLTV/3/224/3221225567/index.m3u8
eleven2[1280*720],rtmp://161.202.204.248/sat/md021
博斯网球[528*32],rtmp://161.202.204.248/sat/md031
KBS世界[1280*720],http://50.7.161.82:8278/streams/d/KBS/playlist.m3u8
OH!k[1280*720],http://50.7.161.82:8278/streams/d/Ohk/playlist.m3u8
ASTRO全佳[1280*720],http://50.7.161.82:8278/streams/d/Quanjia/playlist.m3u8
ASTRO双星[1280*720],http://50.7.161.82:8278/streams/d/Shuangxing/playlist.m3u8
DW新闻[1280*720],https://livecdn.fptplay.net/world/dwenglish_hls.smil/chunklist_b2500000.m3u8
FOX生活[1280*720],https://livecdn.fptplay.net/foxlive/foxlifehd_2000.stream/chunklist.m3u8
FOX电影[1280*720],https://livecdn.fptplay.net/foxlive/foxmovieshd_hls.smil/chunklist_b2500000.m3u8
亚洲美食[1280*720],https://livecdn.fptplay.net/world/afchd_hls.smil/chunklist_b2500000.m3u8
达芬奇儿童[1280*720],https://livecdn.fptplay.net/world/davincihd_hls.smil/chunklist_b2500000.m3u8
法国24[1024*576],https://livecdn.fptplay.net/world/france24_hls.smil/chunklist_b2500000.m3u8
NHK[1280*720],https://nhkw-zh-hlscomp.akamaized.net/8thz5iufork8wjip/playlist.m3u8
astor AOD[1280*720],http://198.16.106.62:8278/streams/d/AodHD/playlist.m3u8
BBC Earth Lifestyle[1280*720],http://198.16.106.62:8278/streams/d/bbclifestyle_zero/playlist.m3u8

BIN
wwwroot/n/.DS_Store vendored Normal file

Binary file not shown.

14
wwwroot/n/cbs_news.ui Normal file
View File

@ -0,0 +1,14 @@
{
"widgettype":"NewVideo",
"id":"vplayer",
"options":{
"h_pattern":{
"iptv.bsppo.com":"referer:https://github.com",
"alicloudccp.com":"referer:https://www.aliyundrive.com/"
},
"source":"https://cbsn-us.cbsnstream.cbsnews.com/out/v1/55a8648e8f134e82a470f83d562deeca/master.m3u8",
"allow_stretch":true,
"keep_ratio":true,
"play":true
}
}

25
wwwroot/n/channel_box.ui Normal file
View File

@ -0,0 +1,25 @@
{
"widgettype":"VBox",
"options":{
"size_hint":[0.5, None],
"height":300
},
"subwidgets":[
{
"widgettype":"Text",
"options":{
"size_hint":[1,1],
"text":"{{params_kw['tv_name']}}",
"wrap":true
}
},
{
"widgettype":"Text",
"options":{
"size_hint":[1,1],
"text":"{{params_kw['channel_delay']}}",
"wrap":true
}
}
]
}

31
wwwroot/n/channel_list.ui Normal file
View File

@ -0,0 +1,31 @@
{
"id":"channel_list",
"widgettype":"HBox",
"options":{
"size_hint":[1,1]
},
"subwidgets":[
{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('./channels_show.ui')}}"
}
},
{
"id":"vplayer",
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('./video.ui')}}"
}
}
],
"binds":[
{
"wid":"search_result",
"event":"on_selected",
"actiontype":"script",
"target":"vplayer",
"script":"self.set_source(args[1].row_data['url'])"
}
]
}

View File

@ -0,0 +1,17 @@
async def get_channels(ns):
sql = "select * from iptvchannels where 1=1 "
if ns.get('search_string') and ns['search_string'] != "":
search_string = ns.get('search_string')
sql = "%s and tv_name like '%%%%%s%%%%'" % (sql, search_string)
rec = await runSQLPaging('iptvdb',sql,ns=ns)
return rec
ns = await request2ns()
print('ns=',ns)
ns['sort'] = 'tv_name'
if not ns.get('page'):
ns['page'] = 1
if not ns.get('userid'):
ns['userid'] = 'Anoumous'
ret = await get_channels(ns)
return ret

86
wwwroot/n/channels.tmpl Normal file
View File

@ -0,0 +1,86 @@
{
"widgettype":"ChannelTester",
"options":{
"searchbox_desc":{
"widgettype":"Form",
"options":{
"size_hint_y":null,
"height":"py::CSize(3)",
"cols":2,
"notoolbar":true,
"inputheight":3,
"labelwidth":0.3,
"fields":[
{
"name":"catelog",
"label":"Catelog",
"datatype":"str",
"uitype":"code",
"uiparams":{
"bgcolor":[0.1,0.1,0.1,1],
"fgcolor":[0.9,0.9,0.9,1],
"data":[
{
"value":"group",
"text":"Group"
},
{
"value":"name",
"text":"Name"
}
]
}
},
{
"name":"search_string",
"label":"Search",
"datatype":"str",
"uiparams":{
"bgcolor":[0.1,0.1,0.1,1],
"fgcolor":[0.9,0.9,0.9,1]
}
}
]
},
"binds":[
{
"wid":"search_string",
"event":"on_changed",
"actiontype":"event",
"datawidget":"self",
"target":"self",
"dispatch_event":"on_submit"
}
]
},
"datagraber_desc":{
"dataurl":"{{entire_url('get_test_channels.dspy')}}",
"params":"py::get_profile()"
},
"chlist_desc":{
"widgettype":"BoxViewer",
"options":{
"dataloader":{
"widgettype":"RelatedLoader",
"options":{
"page_rows":60,
"dataurl":"{{entire_url('get_tested_channels.dspy')}}",
"params":{
}
}
},
"boxwidth":14,
"boxheight":8,
"viewer":{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('channel_box.ui')}}",
"params":{{json.dumps(params_kw)}}
}
}
}
},
"report_chfailed_url":"{{entire_url('report_chfailed.dspy')}}",
"report_chsuccess_url":"{{entire_url('report_chsuccess.dspy')}}"
}
}

23
wwwroot/n/channels.ui Normal file
View File

@ -0,0 +1,23 @@
{
"widgettype":"BoxViewer",
"options":{
"dataloader":{
"widgettype":"RelatedLoader",
"options":{
"page_rows":60,
"dataurl":"{{entire_url('get_channels.dspy')}}",
"params":{
}
}
},
"boxwidth":14,
"boxheight":8,
"viewer":{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('channel_box.ui')}}",
"params":{{json.dumps(params_kw)}}
}
}
}
}

View File

@ -0,0 +1,50 @@
{
"widgettype":"VBox",
"id":"channels_show",
"options":{
"size_hint_y":1,
"size_hint_x":0.3
},
"subwidgets":[
{
"id":"search_key",
"widgettype":"Form",
"options":{
"size_hint_y":null,
"height":100,
"notoolbar":true,
"size_hint_y":null,
"height":"py::CSize(2.4)",
"inputwidth":23,
"labelwidth":0.3,
"inputheight":2,
"fields":[
{
"name":"search_string",
"datatype":"str",
"uitype":"str",
"label":"搜索",
"uitype":"str"
}
]
}
},
{
"id":"search_result",
"widgettype":"urlwidget",
"options": {
"url":"{{entire_url('show_channels.ui')}}"
}
}
],
"binds":[
{
"wid":"search_key.search_string",
"event":"on_changed",
"actiontype":"method",
"datawidget":"search_key",
"target":"search_result",
"method":"loadData"
}
]
}

6
wwwroot/n/cloudpc.ui Normal file
View File

@ -0,0 +1,6 @@
{
"widgettype":"Label",
"options":{
"text":"测试内容"
}
}

2
wwwroot/n/csses.json Normal file
View File

@ -0,0 +1,2 @@
{
}

View File

@ -0,0 +1,3 @@
prog = 'get_channels.dspy'
db = DBPools()

BIN
wwwroot/n/imgs/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
wwwroot/n/imgs/dislike.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
wwwroot/n/imgs/edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
wwwroot/n/imgs/like.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
wwwroot/n/imgs/on_tv.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
wwwroot/n/imgs/play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
wwwroot/n/imgs/test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

1
wwwroot/n/index.dspy Normal file
View File

@ -0,0 +1 @@
return "noting in here"

Some files were not shown because too many files have changed in this diff Show More