mirror of
https://github.com/Balshgit/gpt_chat_bot.git
synced 2025-09-11 22:30:41 +03:00
get gpt service from balshdocker (#16)
This commit is contained in:
parent
59363a495f
commit
61f3a351e2
@ -37,8 +37,8 @@ async def about_bot(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
|||||||
return None
|
return None
|
||||||
await update.effective_message.reply_text(
|
await update.effective_message.reply_text(
|
||||||
"Бот использует бесплатную модель Chat-GPT3.5 для ответов на вопросы. "
|
"Бот использует бесплатную модель Chat-GPT3.5 для ответов на вопросы. "
|
||||||
"Принимает запросы на разных языках. \n\nБот так же умеет переводить голосовые сообщения в текст"
|
"Принимает запросы на разных языках. \n\nБот так же умеет переводить голосовые сообщения в текст."
|
||||||
"просто пришлите голосовуху и получите поток сознания без запятых в виде текста",
|
"Просто пришлите голосовуху и получите поток сознания без запятых в виде текста",
|
||||||
parse_mode='Markdown',
|
parse_mode='Markdown',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
name: ubuntu-gcc13
|
name: build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -48,12 +48,7 @@ jobs:
|
|||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build the Docker image to dev
|
|
||||||
if: github.ref_name == 'dev'
|
|
||||||
run: |
|
|
||||||
docker build . -t ${{ secrets.DOCKERHUB_USERNAME }}/freegpt:dev
|
|
||||||
|
|
||||||
- name: Build the Docker image to main
|
- name: Build the Docker image to main
|
||||||
if: github.ref_name == 'main'
|
if: github.ref_name == 'main'
|
@ -40,7 +40,7 @@ export LIBRARY_PATH=/usr/lib64:$LIBRARY_PATH
|
|||||||
4. Compiling
|
4. Compiling
|
||||||
git clone https://github.com/fantasy-peak/cpp-freegpt-webui.git
|
git clone https://github.com/fantasy-peak/cpp-freegpt-webui.git
|
||||||
cd cpp-freegpt-webui
|
cd cpp-freegpt-webui
|
||||||
xmake build -v
|
xmake build -v -y
|
||||||
xmake install -o .
|
xmake install -o .
|
||||||
cd bin
|
cd bin
|
||||||
./cpp-freegpt-webui ../cfg/cpp-free-gpt.yml
|
./cpp-freegpt-webui ../cfg/cpp-free-gpt.yml
|
||||||
@ -59,9 +59,9 @@ docker pull fantasypeak/freegpt:latest
|
|||||||
|
|
||||||
Run the application using Docker:
|
Run the application using Docker:
|
||||||
```
|
```
|
||||||
docker run --net=host -it --name freegpt fantasypeak/freegpt:latest
|
|
||||||
// OR
|
|
||||||
docker run -p 8858:8858 -it --name freegpt fantasypeak/freegpt:latest
|
docker run -p 8858:8858 -it --name freegpt fantasypeak/freegpt:latest
|
||||||
|
// OR
|
||||||
|
docker run --net=host -it --name freegpt fantasypeak/freegpt:latest
|
||||||
// use http_proxy
|
// use http_proxy
|
||||||
docker run -p 8858:8858 -it --name freegpt -e HTTP_PROXY=http://127.0.0.1:8080 -e CHAT_PATH=/chat fantasypeak/freegpt:latest
|
docker run -p 8858:8858 -it --name freegpt -e HTTP_PROXY=http://127.0.0.1:8080 -e CHAT_PATH=/chat fantasypeak/freegpt:latest
|
||||||
// set active providers
|
// set active providers
|
||||||
@ -119,4 +119,4 @@ Please note the following:
|
|||||||
|
|
||||||
By using this repository or any code related to it, you agree to these terms. The author is not responsible for any
|
By using this repository or any code related to it, you agree to these terms. The author is not responsible for any
|
||||||
copies, forks, or reuploads made by other users. This is the author's only account and repository. To prevent
|
copies, forks, or reuploads made by other users. This is the author's only account and repository. To prevent
|
||||||
impersonation or irresponsible actions, you may comply with the GNU GPL license this Repository uses.
|
impersonation or irresponsible actions, you may comply with the GNU GPL license this Repository uses
|
||||||
|
@ -9,18 +9,18 @@
|
|||||||
<meta property="og:image" content="https://openai.com/content/images/2022/11/ChatGPT.jpg">
|
<meta property="og:image" content="https://openai.com/content/images/2022/11/ChatGPT.jpg">
|
||||||
<meta property="og:description" content="A conversational AI system that listens, learns, and challenges">
|
<meta property="og:description" content="A conversational AI system that listens, learns, and challenges">
|
||||||
<meta property="og:url" content="https://chat.acy.dev">
|
<meta property="og:url" content="https://chat.acy.dev">
|
||||||
<link rel="stylesheet" href="/assets/css/style.css">
|
<link rel="stylesheet" href="{{chat_path}}/assets/css/style.css">
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/assets/img/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{chat_path}}/assets/img/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/assets/img/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{chat_path}}/assets/img/favicon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/assets/img/favicon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{chat_path}}/assets/img/favicon-16x16.png">
|
||||||
<link rel="manifest" href="/assets/img/site.webmanifest">
|
<link rel="manifest" href="{{chat_path}}/assets/img/site.webmanifest">
|
||||||
<script src="/assets/js/icons.js"></script>
|
<script src="{{chat_path}}/assets/js/icons.js"></script>
|
||||||
<script src="/assets/js/chat.js" defer></script>
|
<script src="{{chat_path}}/assets/js/chat.js" defer></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/markdown-it@latest/dist/markdown-it.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/markdown-it@latest/dist/markdown-it.min.js"></script>
|
||||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@latest/build/styles/base16/dracula.min.css">
|
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@latest/build/styles/base16/dracula.min.css">
|
||||||
<script>
|
<script>
|
||||||
const user_image = `<img src="/assets/img/user.png" alt="User Avatar">`;
|
const user_image = `<img src="{{chat_path}}/assets/img/user.png" alt="User Avatar">`;
|
||||||
const gpt_image = `<img src="/assets/img/gpt.png" alt="GPT Avatar">`;
|
const gpt_image = `<img src="{{chat_path}}/assets/img/gpt.png" alt="GPT Avatar">`;
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.hljs {
|
.hljs {
|
||||||
@ -55,8 +55,8 @@
|
|||||||
background: #8b3dff;
|
background: #8b3dff;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="/assets/js/highlight.min.js"></script>
|
<script src="{{chat_path}}/assets/js/highlight.min.js"></script>
|
||||||
<script src="/assets/js/highlightjs-copy.min.js"></script>
|
<script src="{{chat_path}}/assets/js/highlightjs-copy.min.js"></script>
|
||||||
<script>window.conversation_id = {{chat_id}} </script>
|
<script>window.conversation_id = {{chat_id}} </script>
|
||||||
<title>ChatGPT</title>
|
<title>ChatGPT</title>
|
||||||
</head>
|
</head>
|
||||||
@ -79,8 +79,8 @@
|
|||||||
<div class="info">
|
<div class="info">
|
||||||
<i class="fa-regular fa-circle-info"></i>
|
<i class="fa-regular fa-circle-info"></i>
|
||||||
<span class="convo-title">By: Balsh<br>
|
<span class="convo-title">By: Balsh<br>
|
||||||
Version: 0.0.6 <br>
|
Version: 0.0.7 <br>
|
||||||
Release: 2023-09-06<br>
|
Release: 2023-09-28<br>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
"short_name": "",
|
"short_name": "",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/assets/img/android-chrome-192x192.png",
|
"src": "{{chat_path}}/assets/img/android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/android-chrome-512x512.png",
|
"src": "{{chat_path}}/assets/img/android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
|
@ -478,7 +478,7 @@ window.onload = async () => {
|
|||||||
}, 1);
|
}, 1);
|
||||||
|
|
||||||
if (!window.location.href.endsWith(`#`)) {
|
if (!window.location.href.endsWith(`#`)) {
|
||||||
if (/\{{chat_path}}\/.+/.test(window.location.href)) {
|
if (/{{chat_path}}\/.+/.test(window.location.href)) {
|
||||||
await load_conversation(window.conversation_id);
|
await load_conversation(window.conversation_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,9 @@ import re
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
usage = 'git clang-format [OPTIONS] [<commit>] [<commit>] [--] [<file>...]'
|
usage = "git clang-format [OPTIONS] [<commit>] [<commit>] [--] [<file>...]"
|
||||||
|
|
||||||
desc = '''
|
desc = """
|
||||||
If zero or one commits are given, run clang-format on all lines that differ
|
If zero or one commits are given, run clang-format on all lines that differ
|
||||||
between the working directory and <commit>, which defaults to HEAD. Changes are
|
between the working directory and <commit>, which defaults to HEAD. Changes are
|
||||||
only applied to the working directory.
|
only applied to the working directory.
|
||||||
@ -48,14 +48,14 @@ The following git-config settings set the default of the corresponding option:
|
|||||||
clangFormat.commit
|
clangFormat.commit
|
||||||
clangFormat.extension
|
clangFormat.extension
|
||||||
clangFormat.style
|
clangFormat.style
|
||||||
'''
|
"""
|
||||||
|
|
||||||
# Name of the temporary index file in which save the output of clang-format.
|
# Name of the temporary index file in which save the output of clang-format.
|
||||||
# This file is created within the .git directory.
|
# This file is created within the .git directory.
|
||||||
temp_index_basename = 'clang-format-index'
|
temp_index_basename = "clang-format-index"
|
||||||
|
|
||||||
|
|
||||||
Range = collections.namedtuple('Range', 'start, count')
|
Range = collections.namedtuple("Range", "start, count")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -66,61 +66,87 @@ def main():
|
|||||||
# nargs=argparse.REMAINDER disallows options after positionals.)
|
# nargs=argparse.REMAINDER disallows options after positionals.)
|
||||||
argv = sys.argv[1:]
|
argv = sys.argv[1:]
|
||||||
try:
|
try:
|
||||||
idx = argv.index('--')
|
idx = argv.index("--")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
dash_dash = []
|
dash_dash = []
|
||||||
else:
|
else:
|
||||||
dash_dash = argv[idx:]
|
dash_dash = argv[idx:]
|
||||||
argv = argv[:idx]
|
argv = argv[:idx]
|
||||||
|
|
||||||
default_extensions = ','.join(
|
default_extensions = ",".join(
|
||||||
[
|
[
|
||||||
# From clang/lib/Frontend/FrontendOptions.cpp, all lower case
|
# From clang/lib/Frontend/FrontendOptions.cpp, all lower case
|
||||||
'c',
|
"c",
|
||||||
'h', # C
|
"h", # C
|
||||||
'm', # ObjC
|
"m", # ObjC
|
||||||
'mm', # ObjC++
|
"mm", # ObjC++
|
||||||
'cc',
|
"cc",
|
||||||
'cp',
|
"cp",
|
||||||
'cpp',
|
"cpp",
|
||||||
'c++',
|
"c++",
|
||||||
'cxx',
|
"cxx",
|
||||||
'hh',
|
"hh",
|
||||||
'hpp',
|
"hpp",
|
||||||
'hxx', # C++
|
"hxx", # C++
|
||||||
'cu', # CUDA
|
"cu", # CUDA
|
||||||
# Other languages that clang-format supports
|
# Other languages that clang-format supports
|
||||||
'proto',
|
"proto",
|
||||||
'protodevel', # Protocol Buffers
|
"protodevel", # Protocol Buffers
|
||||||
'java', # Java
|
"java", # Java
|
||||||
'js', # JavaScript
|
"js", # JavaScript
|
||||||
'ts', # TypeScript
|
"ts", # TypeScript
|
||||||
'cs', # C Sharp
|
"cs", # C Sharp
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
p = argparse.ArgumentParser(usage=usage, formatter_class=argparse.RawDescriptionHelpFormatter, description=desc)
|
p = argparse.ArgumentParser(
|
||||||
p.add_argument('--binary', default=config.get('clangformat.binary', 'clang-format'), help='path to clang-format'),
|
usage=usage,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description=desc,
|
||||||
|
)
|
||||||
p.add_argument(
|
p.add_argument(
|
||||||
'--commit', default=config.get('clangformat.commit', 'HEAD'), help='default commit to use if none is specified'
|
"--binary",
|
||||||
|
default=config.get("clangformat.binary", "clang-format"),
|
||||||
|
help="path to clang-format",
|
||||||
),
|
),
|
||||||
p.add_argument('--diff', action='store_true', help='print a diff instead of applying the changes')
|
|
||||||
p.add_argument(
|
p.add_argument(
|
||||||
'--extensions',
|
"--commit",
|
||||||
default=config.get('clangformat.extensions', default_extensions),
|
default=config.get("clangformat.commit", "HEAD"),
|
||||||
help=('comma-separated list of file extensions to format, ' 'excluding the period and case-insensitive'),
|
help="default commit to use if none is specified",
|
||||||
),
|
),
|
||||||
p.add_argument('-f', '--force', action='store_true', help='allow changes to unstaged files')
|
p.add_argument(
|
||||||
p.add_argument('-p', '--patch', action='store_true', help='select hunks interactively')
|
"--diff",
|
||||||
p.add_argument('-q', '--quiet', action='count', default=0, help='print less information')
|
action="store_true",
|
||||||
p.add_argument('--style', default=config.get('clangformat.style', None), help='passed to clang-format'),
|
help="print a diff instead of applying the changes",
|
||||||
p.add_argument('-v', '--verbose', action='count', default=0, help='print extra information')
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--extensions",
|
||||||
|
default=config.get("clangformat.extensions", default_extensions),
|
||||||
|
help=("comma-separated list of file extensions to format, " "excluding the period and case-insensitive"),
|
||||||
|
),
|
||||||
|
p.add_argument("-f", "--force", action="store_true", help="allow changes to unstaged files")
|
||||||
|
p.add_argument("-p", "--patch", action="store_true", help="select hunks interactively")
|
||||||
|
p.add_argument("-q", "--quiet", action="count", default=0, help="print less information")
|
||||||
|
p.add_argument(
|
||||||
|
"--style",
|
||||||
|
default=config.get("clangformat.style", None),
|
||||||
|
help="passed to clang-format",
|
||||||
|
),
|
||||||
|
p.add_argument("-v", "--verbose", action="count", default=0, help="print extra information")
|
||||||
# We gather all the remaining positional arguments into 'args' since we need
|
# We gather all the remaining positional arguments into 'args' since we need
|
||||||
# to use some heuristics to determine whether or not <commit> was present.
|
# to use some heuristics to determine whether or not <commit> was present.
|
||||||
# However, to print pretty messages, we make use of metavar and help.
|
# However, to print pretty messages, we make use of metavar and help.
|
||||||
p.add_argument('args', nargs='*', metavar='<commit>', help='revision from which to compute the diff')
|
|
||||||
p.add_argument(
|
p.add_argument(
|
||||||
'ignored', nargs='*', metavar='<file>...', help='if specified, only consider differences in these files'
|
"args",
|
||||||
|
nargs="*",
|
||||||
|
metavar="<commit>",
|
||||||
|
help="revision from which to compute the diff",
|
||||||
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"ignored",
|
||||||
|
nargs="*",
|
||||||
|
metavar="<file>...",
|
||||||
|
help="if specified, only consider differences in these files",
|
||||||
)
|
)
|
||||||
opts = p.parse_args(argv)
|
opts = p.parse_args(argv)
|
||||||
|
|
||||||
@ -130,26 +156,26 @@ def main():
|
|||||||
commits, files = interpret_args(opts.args, dash_dash, opts.commit)
|
commits, files = interpret_args(opts.args, dash_dash, opts.commit)
|
||||||
if len(commits) > 1:
|
if len(commits) > 1:
|
||||||
if not opts.diff:
|
if not opts.diff:
|
||||||
die('--diff is required when two commits are given')
|
die("--diff is required when two commits are given")
|
||||||
else:
|
else:
|
||||||
if len(commits) > 2:
|
if len(commits) > 2:
|
||||||
die('at most two commits allowed; %d given' % len(commits))
|
die("at most two commits allowed; %d given" % len(commits))
|
||||||
changed_lines = compute_diff_and_extract_lines(commits, files)
|
changed_lines = compute_diff_and_extract_lines(commits, files)
|
||||||
if opts.verbose >= 1:
|
if opts.verbose >= 1:
|
||||||
ignored_files = set(changed_lines)
|
ignored_files = set(changed_lines)
|
||||||
filter_by_extension(changed_lines, opts.extensions.lower().split(','))
|
filter_by_extension(changed_lines, opts.extensions.lower().split(","))
|
||||||
if opts.verbose >= 1:
|
if opts.verbose >= 1:
|
||||||
ignored_files.difference_update(changed_lines)
|
ignored_files.difference_update(changed_lines)
|
||||||
if ignored_files:
|
if ignored_files:
|
||||||
print('Ignoring changes in the following files (wrong extension):')
|
print("Ignoring changes in the following files (wrong extension):")
|
||||||
for filename in ignored_files:
|
for filename in ignored_files:
|
||||||
print(' %s' % filename)
|
print(" %s" % filename)
|
||||||
if changed_lines:
|
if changed_lines:
|
||||||
print('Running clang-format on the following files:')
|
print("Running clang-format on the following files:")
|
||||||
for filename in changed_lines:
|
for filename in changed_lines:
|
||||||
print(' %s' % filename)
|
print(" %s" % filename)
|
||||||
if not changed_lines:
|
if not changed_lines:
|
||||||
print('no modified files to format')
|
print("no modified files to format")
|
||||||
return
|
return
|
||||||
# The computed diff outputs absolute paths, so we must cd before accessing
|
# The computed diff outputs absolute paths, so we must cd before accessing
|
||||||
# those files.
|
# those files.
|
||||||
@ -163,19 +189,19 @@ def main():
|
|||||||
old_tree = create_tree_from_workdir(changed_lines)
|
old_tree = create_tree_from_workdir(changed_lines)
|
||||||
new_tree = run_clang_format_and_save_to_tree(changed_lines, binary=opts.binary, style=opts.style)
|
new_tree = run_clang_format_and_save_to_tree(changed_lines, binary=opts.binary, style=opts.style)
|
||||||
if opts.verbose >= 1:
|
if opts.verbose >= 1:
|
||||||
print('old tree: %s' % old_tree)
|
print("old tree: %s" % old_tree)
|
||||||
print('new tree: %s' % new_tree)
|
print("new tree: %s" % new_tree)
|
||||||
if old_tree == new_tree:
|
if old_tree == new_tree:
|
||||||
if opts.verbose >= 0:
|
if opts.verbose >= 0:
|
||||||
print('clang-format did not modify any files')
|
print("clang-format did not modify any files")
|
||||||
elif opts.diff:
|
elif opts.diff:
|
||||||
print_diff(old_tree, new_tree)
|
print_diff(old_tree, new_tree)
|
||||||
else:
|
else:
|
||||||
changed_files = apply_changes(old_tree, new_tree, force=opts.force, patch_mode=opts.patch)
|
changed_files = apply_changes(old_tree, new_tree, force=opts.force, patch_mode=opts.patch)
|
||||||
if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1:
|
if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1:
|
||||||
print('changed files:')
|
print("changed files:")
|
||||||
for filename in changed_files:
|
for filename in changed_files:
|
||||||
print(' %s' % filename)
|
print(" %s" % filename)
|
||||||
|
|
||||||
|
|
||||||
def load_git_config(non_string_options=None):
|
def load_git_config(non_string_options=None):
|
||||||
@ -187,11 +213,11 @@ def load_git_config(non_string_options=None):
|
|||||||
if non_string_options is None:
|
if non_string_options is None:
|
||||||
non_string_options = {}
|
non_string_options = {}
|
||||||
out = {}
|
out = {}
|
||||||
for entry in run('git', 'config', '--list', '--null').split('\0'):
|
for entry in run("git", "config", "--list", "--null").split("\0"):
|
||||||
if entry:
|
if entry:
|
||||||
name, value = entry.split('\n', 1)
|
name, value = entry.split("\n", 1)
|
||||||
if name in non_string_options:
|
if name in non_string_options:
|
||||||
value = run('git', 'config', non_string_options[name], name)
|
value = run("git", "config", non_string_options[name], name)
|
||||||
out[name] = value
|
out[name] = value
|
||||||
return out
|
return out
|
||||||
|
|
||||||
@ -213,7 +239,7 @@ def interpret_args(args, dash_dash, default_commit):
|
|||||||
commits = args
|
commits = args
|
||||||
for commit in commits:
|
for commit in commits:
|
||||||
object_type = get_object_type(commit)
|
object_type = get_object_type(commit)
|
||||||
if object_type not in ('commit', 'tag'):
|
if object_type not in ("commit", "tag"):
|
||||||
if object_type is None:
|
if object_type is None:
|
||||||
die("'%s' is not a commit" % commit)
|
die("'%s' is not a commit" % commit)
|
||||||
else:
|
else:
|
||||||
@ -238,19 +264,19 @@ def disambiguate_revision(value):
|
|||||||
"""Returns True if `value` is a revision, False if it is a file, or dies."""
|
"""Returns True if `value` is a revision, False if it is a file, or dies."""
|
||||||
# If `value` is ambiguous (neither a commit nor a file), the following
|
# If `value` is ambiguous (neither a commit nor a file), the following
|
||||||
# command will die with an appropriate error message.
|
# command will die with an appropriate error message.
|
||||||
run('git', 'rev-parse', value, verbose=False)
|
run("git", "rev-parse", value, verbose=False)
|
||||||
object_type = get_object_type(value)
|
object_type = get_object_type(value)
|
||||||
if object_type is None:
|
if object_type is None:
|
||||||
return False
|
return False
|
||||||
if object_type in ('commit', 'tag'):
|
if object_type in ("commit", "tag"):
|
||||||
return True
|
return True
|
||||||
die('`%s` is a %s, but a commit or filename was expected' % (value, object_type))
|
die("`%s` is a %s, but a commit or filename was expected" % (value, object_type))
|
||||||
|
|
||||||
|
|
||||||
def get_object_type(value):
|
def get_object_type(value):
|
||||||
"""Returns a string description of an object's type, or None if it is not
|
"""Returns a string description of an object's type, or None if it is not
|
||||||
a valid git object."""
|
a valid git object."""
|
||||||
cmd = ['git', 'cat-file', '-t', value]
|
cmd = ["git", "cat-file", "-t", value]
|
||||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
if p.returncode != 0:
|
if p.returncode != 0:
|
||||||
@ -277,10 +303,10 @@ def compute_diff(commits, files):
|
|||||||
differences between the working directory and the first commit if a single
|
differences between the working directory and the first commit if a single
|
||||||
one was specified, or the difference between both specified commits, filtered
|
one was specified, or the difference between both specified commits, filtered
|
||||||
on `files` (if non-empty). Zero context lines are used in the patch."""
|
on `files` (if non-empty). Zero context lines are used in the patch."""
|
||||||
git_tool = 'diff-index'
|
git_tool = "diff-index"
|
||||||
if len(commits) > 1:
|
if len(commits) > 1:
|
||||||
git_tool = 'diff-tree'
|
git_tool = "diff-tree"
|
||||||
cmd = ['git', git_tool, '-p', '-U0'] + commits + ['--']
|
cmd = ["git", git_tool, "-p", "-U0"] + commits + ["--"]
|
||||||
cmd.extend(files)
|
cmd.extend(files)
|
||||||
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
p.stdin.close()
|
p.stdin.close()
|
||||||
@ -299,10 +325,10 @@ def extract_lines(patch_file):
|
|||||||
matches = {}
|
matches = {}
|
||||||
for line in patch_file:
|
for line in patch_file:
|
||||||
line = convert_string(line)
|
line = convert_string(line)
|
||||||
match = re.search(r'^\+\+\+\ [^/]+/(.*)', line)
|
match = re.search(r"^\+\+\+\ [^/]+/(.*)", line)
|
||||||
if match:
|
if match:
|
||||||
filename = match.group(1).rstrip('\r\n')
|
filename = match.group(1).rstrip("\r\n")
|
||||||
match = re.search(r'^@@ -[0-9,]+ \+(\d+)(,(\d+))?', line)
|
match = re.search(r"^@@ -[0-9,]+ \+(\d+)(,(\d+))?", line)
|
||||||
if match:
|
if match:
|
||||||
start_line = int(match.group(1))
|
start_line = int(match.group(1))
|
||||||
line_count = 1
|
line_count = 1
|
||||||
@ -320,8 +346,8 @@ def filter_by_extension(dictionary, allowed_extensions):
|
|||||||
excluding the period."""
|
excluding the period."""
|
||||||
allowed_extensions = frozenset(allowed_extensions)
|
allowed_extensions = frozenset(allowed_extensions)
|
||||||
for filename in list(dictionary.keys()):
|
for filename in list(dictionary.keys()):
|
||||||
base_ext = filename.rsplit('.', 1)
|
base_ext = filename.rsplit(".", 1)
|
||||||
if len(base_ext) == 1 and '' in allowed_extensions:
|
if len(base_ext) == 1 and "" in allowed_extensions:
|
||||||
continue
|
continue
|
||||||
if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions:
|
if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions:
|
||||||
del dictionary[filename]
|
del dictionary[filename]
|
||||||
@ -329,7 +355,7 @@ def filter_by_extension(dictionary, allowed_extensions):
|
|||||||
|
|
||||||
def cd_to_toplevel():
|
def cd_to_toplevel():
|
||||||
"""Change to the top level of the git repository."""
|
"""Change to the top level of the git repository."""
|
||||||
toplevel = run('git', 'rev-parse', '--show-toplevel')
|
toplevel = run("git", "rev-parse", "--show-toplevel")
|
||||||
os.chdir(toplevel)
|
os.chdir(toplevel)
|
||||||
|
|
||||||
|
|
||||||
@ -337,10 +363,10 @@ def create_tree_from_workdir(filenames):
|
|||||||
"""Create a new git tree with the given files from the working directory.
|
"""Create a new git tree with the given files from the working directory.
|
||||||
|
|
||||||
Returns the object ID (SHA-1) of the created tree."""
|
Returns the object ID (SHA-1) of the created tree."""
|
||||||
return create_tree(filenames, '--stdin')
|
return create_tree(filenames, "--stdin")
|
||||||
|
|
||||||
|
|
||||||
def run_clang_format_and_save_to_tree(changed_lines, revision=None, binary='clang-format', style=None):
|
def run_clang_format_and_save_to_tree(changed_lines, revision=None, binary="clang-format", style=None):
|
||||||
"""Run clang-format on each file and save the result to a git tree.
|
"""Run clang-format on each file and save the result to a git tree.
|
||||||
|
|
||||||
Returns the object ID (SHA-1) of the created tree."""
|
Returns the object ID (SHA-1) of the created tree."""
|
||||||
@ -355,9 +381,9 @@ def run_clang_format_and_save_to_tree(changed_lines, revision=None, binary='clan
|
|||||||
for filename, line_ranges in iteritems(changed_lines):
|
for filename, line_ranges in iteritems(changed_lines):
|
||||||
if revision:
|
if revision:
|
||||||
git_metadata_cmd = [
|
git_metadata_cmd = [
|
||||||
'git',
|
"git",
|
||||||
'ls-tree',
|
"ls-tree",
|
||||||
'%s:%s' % (revision, os.path.dirname(filename)),
|
"%s:%s" % (revision, os.path.dirname(filename)),
|
||||||
os.path.basename(filename),
|
os.path.basename(filename),
|
||||||
]
|
]
|
||||||
git_metadata = subprocess.Popen(git_metadata_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
git_metadata = subprocess.Popen(git_metadata_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
@ -366,12 +392,12 @@ def run_clang_format_and_save_to_tree(changed_lines, revision=None, binary='clan
|
|||||||
else:
|
else:
|
||||||
mode = oct(os.stat(filename).st_mode)
|
mode = oct(os.stat(filename).st_mode)
|
||||||
# Adjust python3 octal format so that it matches what git expects
|
# Adjust python3 octal format so that it matches what git expects
|
||||||
if mode.startswith('0o'):
|
if mode.startswith("0o"):
|
||||||
mode = '0' + mode[2:]
|
mode = "0" + mode[2:]
|
||||||
blob_id = clang_format_to_blob(filename, line_ranges, revision=revision, binary=binary, style=style)
|
blob_id = clang_format_to_blob(filename, line_ranges, revision=revision, binary=binary, style=style)
|
||||||
yield '%s %s\t%s' % (mode, blob_id, filename)
|
yield "%s %s\t%s" % (mode, blob_id, filename)
|
||||||
|
|
||||||
return create_tree(index_info_generator(), '--index-info')
|
return create_tree(index_info_generator(), "--index-info")
|
||||||
|
|
||||||
|
|
||||||
def create_tree(input_lines, mode):
|
def create_tree(input_lines, mode):
|
||||||
@ -381,20 +407,20 @@ def create_tree(input_lines, mode):
|
|||||||
'--index-info' is must be a list of values suitable for "git update-index
|
'--index-info' is must be a list of values suitable for "git update-index
|
||||||
--index-info", such as "<mode> <SP> <sha1> <TAB> <filename>". Any other mode
|
--index-info", such as "<mode> <SP> <sha1> <TAB> <filename>". Any other mode
|
||||||
is invalid."""
|
is invalid."""
|
||||||
assert mode in ('--stdin', '--index-info')
|
assert mode in ("--stdin", "--index-info")
|
||||||
cmd = ['git', 'update-index', '--add', '-z', mode]
|
cmd = ["git", "update-index", "--add", "-z", mode]
|
||||||
with temporary_index_file():
|
with temporary_index_file():
|
||||||
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
|
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
|
||||||
for line in input_lines:
|
for line in input_lines:
|
||||||
p.stdin.write(to_bytes('%s\0' % line))
|
p.stdin.write(to_bytes("%s\0" % line))
|
||||||
p.stdin.close()
|
p.stdin.close()
|
||||||
if p.wait() != 0:
|
if p.wait() != 0:
|
||||||
die('`%s` failed' % ' '.join(cmd))
|
die("`%s` failed" % " ".join(cmd))
|
||||||
tree_id = run('git', 'write-tree')
|
tree_id = run("git", "write-tree")
|
||||||
return tree_id
|
return tree_id
|
||||||
|
|
||||||
|
|
||||||
def clang_format_to_blob(filename, line_ranges, revision=None, binary='clang-format', style=None):
|
def clang_format_to_blob(filename, line_ranges, revision=None, binary="clang-format", style=None):
|
||||||
"""Run clang-format on the given file and save the result to a git blob.
|
"""Run clang-format on the given file and save the result to a git blob.
|
||||||
|
|
||||||
Runs on the file in `revision` if not None, or on the file in the working
|
Runs on the file in `revision` if not None, or on the file in the working
|
||||||
@ -403,13 +429,13 @@ def clang_format_to_blob(filename, line_ranges, revision=None, binary='clang-for
|
|||||||
Returns the object ID (SHA-1) of the created blob."""
|
Returns the object ID (SHA-1) of the created blob."""
|
||||||
clang_format_cmd = [binary]
|
clang_format_cmd = [binary]
|
||||||
if style:
|
if style:
|
||||||
clang_format_cmd.extend(['-style=' + style])
|
clang_format_cmd.extend(["-style=" + style])
|
||||||
clang_format_cmd.extend(
|
clang_format_cmd.extend(
|
||||||
['-lines=%s:%s' % (start_line, start_line + line_count - 1) for start_line, line_count in line_ranges]
|
["-lines=%s:%s" % (start_line, start_line + line_count - 1) for start_line, line_count in line_ranges]
|
||||||
)
|
)
|
||||||
if revision:
|
if revision:
|
||||||
clang_format_cmd.extend(['-assume-filename=' + filename])
|
clang_format_cmd.extend(["-assume-filename=" + filename])
|
||||||
git_show_cmd = ['git', 'cat-file', 'blob', '%s:%s' % (revision, filename)]
|
git_show_cmd = ["git", "cat-file", "blob", "%s:%s" % (revision, filename)]
|
||||||
git_show = subprocess.Popen(git_show_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
git_show = subprocess.Popen(git_show_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
git_show.stdin.close()
|
git_show.stdin.close()
|
||||||
clang_format_stdin = git_show.stdout
|
clang_format_stdin = git_show.stdout
|
||||||
@ -427,17 +453,17 @@ def clang_format_to_blob(filename, line_ranges, revision=None, binary='clang-for
|
|||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
clang_format_stdin.close()
|
clang_format_stdin.close()
|
||||||
hash_object_cmd = ['git', 'hash-object', '-w', '--path=' + filename, '--stdin']
|
hash_object_cmd = ["git", "hash-object", "-w", "--path=" + filename, "--stdin"]
|
||||||
hash_object = subprocess.Popen(hash_object_cmd, stdin=clang_format.stdout, stdout=subprocess.PIPE)
|
hash_object = subprocess.Popen(hash_object_cmd, stdin=clang_format.stdout, stdout=subprocess.PIPE)
|
||||||
clang_format.stdout.close()
|
clang_format.stdout.close()
|
||||||
stdout = hash_object.communicate()[0]
|
stdout = hash_object.communicate()[0]
|
||||||
if hash_object.returncode != 0:
|
if hash_object.returncode != 0:
|
||||||
die('`%s` failed' % ' '.join(hash_object_cmd))
|
die("`%s` failed" % " ".join(hash_object_cmd))
|
||||||
if clang_format.wait() != 0:
|
if clang_format.wait() != 0:
|
||||||
die('`%s` failed' % ' '.join(clang_format_cmd))
|
die("`%s` failed" % " ".join(clang_format_cmd))
|
||||||
if git_show and git_show.wait() != 0:
|
if git_show and git_show.wait() != 0:
|
||||||
die('`%s` failed' % ' '.join(git_show_cmd))
|
die("`%s` failed" % " ".join(git_show_cmd))
|
||||||
return convert_string(stdout).rstrip('\r\n')
|
return convert_string(stdout).rstrip("\r\n")
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
@ -445,15 +471,15 @@ def temporary_index_file(tree=None):
|
|||||||
"""Context manager for setting GIT_INDEX_FILE to a temporary file and deleting
|
"""Context manager for setting GIT_INDEX_FILE to a temporary file and deleting
|
||||||
the file afterward."""
|
the file afterward."""
|
||||||
index_path = create_temporary_index(tree)
|
index_path = create_temporary_index(tree)
|
||||||
old_index_path = os.environ.get('GIT_INDEX_FILE')
|
old_index_path = os.environ.get("GIT_INDEX_FILE")
|
||||||
os.environ['GIT_INDEX_FILE'] = index_path
|
os.environ["GIT_INDEX_FILE"] = index_path
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
if old_index_path is None:
|
if old_index_path is None:
|
||||||
del os.environ['GIT_INDEX_FILE']
|
del os.environ["GIT_INDEX_FILE"]
|
||||||
else:
|
else:
|
||||||
os.environ['GIT_INDEX_FILE'] = old_index_path
|
os.environ["GIT_INDEX_FILE"] = old_index_path
|
||||||
os.remove(index_path)
|
os.remove(index_path)
|
||||||
|
|
||||||
|
|
||||||
@ -462,11 +488,11 @@ def create_temporary_index(tree=None):
|
|||||||
|
|
||||||
If `tree` is not None, use that as the tree to read in. Otherwise, an
|
If `tree` is not None, use that as the tree to read in. Otherwise, an
|
||||||
empty index is created."""
|
empty index is created."""
|
||||||
gitdir = run('git', 'rev-parse', '--git-dir')
|
gitdir = run("git", "rev-parse", "--git-dir")
|
||||||
path = os.path.join(gitdir, temp_index_basename)
|
path = os.path.join(gitdir, temp_index_basename)
|
||||||
if tree is None:
|
if tree is None:
|
||||||
tree = '--empty'
|
tree = "--empty"
|
||||||
run('git', 'read-tree', '--index-output=' + path, tree)
|
run("git", "read-tree", "--index-output=" + path, tree)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
@ -479,7 +505,7 @@ def print_diff(old_tree, new_tree):
|
|||||||
# We also only print modified files since `new_tree` only contains the files
|
# We also only print modified files since `new_tree` only contains the files
|
||||||
# that were modified, so unmodified files would show as deleted without the
|
# that were modified, so unmodified files would show as deleted without the
|
||||||
# filter.
|
# filter.
|
||||||
subprocess.check_call(['git', 'diff', '--diff-filter=M', old_tree, new_tree, '--'])
|
subprocess.check_call(["git", "diff", "--diff-filter=M", old_tree, new_tree, "--"])
|
||||||
|
|
||||||
|
|
||||||
def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
|
def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
|
||||||
@ -488,16 +514,28 @@ def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
|
|||||||
Bails if there are local changes in those files and not `force`. If
|
Bails if there are local changes in those files and not `force`. If
|
||||||
`patch_mode`, runs `git checkout --patch` to select hunks interactively."""
|
`patch_mode`, runs `git checkout --patch` to select hunks interactively."""
|
||||||
changed_files = (
|
changed_files = (
|
||||||
run('git', 'diff-tree', '--diff-filter=M', '-r', '-z', '--name-only', old_tree, new_tree)
|
run(
|
||||||
.rstrip('\0')
|
"git",
|
||||||
.split('\0')
|
"diff-tree",
|
||||||
|
"--diff-filter=M",
|
||||||
|
"-r",
|
||||||
|
"-z",
|
||||||
|
"--name-only",
|
||||||
|
old_tree,
|
||||||
|
new_tree,
|
||||||
|
)
|
||||||
|
.rstrip("\0")
|
||||||
|
.split("\0")
|
||||||
)
|
)
|
||||||
if not force:
|
if not force:
|
||||||
unstaged_files = run('git', 'diff-files', '--name-status', *changed_files)
|
unstaged_files = run("git", "diff-files", "--name-status", *changed_files)
|
||||||
if unstaged_files:
|
if unstaged_files:
|
||||||
print('The following files would be modified but ' 'have unstaged changes:', file=sys.stderr)
|
print(
|
||||||
|
"The following files would be modified but " "have unstaged changes:",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
print(unstaged_files, file=sys.stderr)
|
print(unstaged_files, file=sys.stderr)
|
||||||
print('Please commit, stage, or stash them first.', file=sys.stderr)
|
print("Please commit, stage, or stash them first.", file=sys.stderr)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
if patch_mode:
|
if patch_mode:
|
||||||
# In patch mode, we could just as well create an index from the new tree
|
# In patch mode, we could just as well create an index from the new tree
|
||||||
@ -507,17 +545,17 @@ def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
|
|||||||
# better message, "Apply ... to index and worktree". This is not quite
|
# better message, "Apply ... to index and worktree". This is not quite
|
||||||
# right, since it won't be applied to the user's index, but oh well.
|
# right, since it won't be applied to the user's index, but oh well.
|
||||||
with temporary_index_file(old_tree):
|
with temporary_index_file(old_tree):
|
||||||
subprocess.check_call(['git', 'checkout', '--patch', new_tree])
|
subprocess.check_call(["git", "checkout", "--patch", new_tree])
|
||||||
else:
|
else:
|
||||||
with temporary_index_file(new_tree):
|
with temporary_index_file(new_tree):
|
||||||
run('git', 'checkout-index', '-a', '-f')
|
run("git", "checkout-index", "-a", "-f")
|
||||||
return changed_files
|
return changed_files
|
||||||
|
|
||||||
|
|
||||||
def run(*args, **kwargs):
|
def run(*args, **kwargs):
|
||||||
stdin = kwargs.pop('stdin', '')
|
stdin = kwargs.pop("stdin", "")
|
||||||
verbose = kwargs.pop('verbose', True)
|
verbose = kwargs.pop("verbose", True)
|
||||||
strip = kwargs.pop('strip', True)
|
strip = kwargs.pop("strip", True)
|
||||||
for name in kwargs:
|
for name in kwargs:
|
||||||
raise TypeError("run() got an unexpected keyword argument '%s'" % name)
|
raise TypeError("run() got an unexpected keyword argument '%s'" % name)
|
||||||
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
|
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
|
||||||
@ -529,20 +567,20 @@ def run(*args, **kwargs):
|
|||||||
if p.returncode == 0:
|
if p.returncode == 0:
|
||||||
if stderr:
|
if stderr:
|
||||||
if verbose:
|
if verbose:
|
||||||
print('`%s` printed to stderr:' % ' '.join(args), file=sys.stderr)
|
print("`%s` printed to stderr:" % " ".join(args), file=sys.stderr)
|
||||||
print(stderr.rstrip(), file=sys.stderr)
|
print(stderr.rstrip(), file=sys.stderr)
|
||||||
if strip:
|
if strip:
|
||||||
stdout = stdout.rstrip('\r\n')
|
stdout = stdout.rstrip("\r\n")
|
||||||
return stdout
|
return stdout
|
||||||
if verbose:
|
if verbose:
|
||||||
print('`%s` returned %s' % (' '.join(args), p.returncode), file=sys.stderr)
|
print("`%s` returned %s" % (" ".join(args), p.returncode), file=sys.stderr)
|
||||||
if stderr:
|
if stderr:
|
||||||
print(stderr.rstrip(), file=sys.stderr)
|
print(stderr.rstrip(), file=sys.stderr)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
|
|
||||||
def die(message):
|
def die(message):
|
||||||
print('error:', message, file=sys.stderr)
|
print("error:", message, file=sys.stderr)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
|
|
||||||
@ -550,23 +588,23 @@ def to_bytes(str_input):
|
|||||||
# Encode to UTF-8 to get binary data.
|
# Encode to UTF-8 to get binary data.
|
||||||
if isinstance(str_input, bytes):
|
if isinstance(str_input, bytes):
|
||||||
return str_input
|
return str_input
|
||||||
return str_input.encode('utf-8')
|
return str_input.encode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
def to_string(bytes_input):
|
def to_string(bytes_input):
|
||||||
if isinstance(bytes_input, str):
|
if isinstance(bytes_input, str):
|
||||||
return bytes_input
|
return bytes_input
|
||||||
return bytes_input.encode('utf-8')
|
return bytes_input.encode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
def convert_string(bytes_input):
|
def convert_string(bytes_input):
|
||||||
try:
|
try:
|
||||||
return to_string(bytes_input.decode('utf-8'))
|
return to_string(bytes_input.decode("utf-8"))
|
||||||
except AttributeError: # 'str' object has no attribute 'decode'.
|
except AttributeError: # 'str' object has no attribute 'decode'.
|
||||||
return str(bytes_input)
|
return str(bytes_input)
|
||||||
except UnicodeError:
|
except UnicodeError:
|
||||||
return str(bytes_input)
|
return str(bytes_input)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -38,6 +38,7 @@ public:
|
|||||||
boost::asio::awaitable<void> vitalentum(std::shared_ptr<Channel>, nlohmann::json);
|
boost::asio::awaitable<void> vitalentum(std::shared_ptr<Channel>, nlohmann::json);
|
||||||
boost::asio::awaitable<void> gptGo(std::shared_ptr<Channel>, nlohmann::json);
|
boost::asio::awaitable<void> gptGo(std::shared_ptr<Channel>, nlohmann::json);
|
||||||
boost::asio::awaitable<void> aibn(std::shared_ptr<Channel>, nlohmann::json);
|
boost::asio::awaitable<void> aibn(std::shared_ptr<Channel>, nlohmann::json);
|
||||||
|
boost::asio::awaitable<void> chatGptDuo(std::shared_ptr<Channel>, nlohmann::json);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::asio::awaitable<std::expected<boost::beast::ssl_stream<boost::beast::tcp_stream>, std::string>>
|
boost::asio::awaitable<std::expected<boost::beast::ssl_stream<boost::beast::tcp_stream>, std::string>>
|
||||||
|
@ -517,7 +517,7 @@ std::optional<HttpResponse> getCookie(CURL* curl, const std::string& url, const
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
FreeGpt::FreeGpt(Config& cfg)
|
FreeGpt::FreeGpt(Config& cfg)
|
||||||
: m_cfg(cfg), m_thread_pool_ptr(std::make_shared<boost::asio::thread_pool>(m_cfg.work_thread_num)) {}
|
: m_cfg(cfg), m_thread_pool_ptr(std::make_shared<boost::asio::thread_pool>(m_cfg.work_thread_num * 2)) {}
|
||||||
|
|
||||||
boost::asio::awaitable<std::expected<boost::beast::ssl_stream<boost::beast::tcp_stream>, std::string>>
|
boost::asio::awaitable<std::expected<boost::beast::ssl_stream<boost::beast::tcp_stream>, std::string>>
|
||||||
FreeGpt::createHttpClient(boost::asio::ssl::context& ctx, std::string_view host, std::string_view port) {
|
FreeGpt::createHttpClient(boost::asio::ssl::context& ctx, std::string_view host, std::string_view port) {
|
||||||
@ -2116,8 +2116,6 @@ boost::asio::awaitable<void> FreeGpt::ylokh(std::shared_ptr<Channel> ch, nlohman
|
|||||||
boost::system::error_code err{};
|
boost::system::error_code err{};
|
||||||
ScopeExit auto_exit{[&] { ch->close(); }};
|
ScopeExit auto_exit{[&] { ch->close(); }};
|
||||||
|
|
||||||
auto prompt = json.at("meta").at("content").at("parts").at(0).at("content").get<std::string>();
|
|
||||||
|
|
||||||
constexpr std::string_view host = "chatapi.ylokh.xyz";
|
constexpr std::string_view host = "chatapi.ylokh.xyz";
|
||||||
constexpr std::string_view port = "443";
|
constexpr std::string_view port = "443";
|
||||||
|
|
||||||
@ -2153,10 +2151,6 @@ boost::asio::awaitable<void> FreeGpt::ylokh(std::shared_ptr<Channel> ch, nlohman
|
|||||||
{
|
{
|
||||||
"role":"system",
|
"role":"system",
|
||||||
"content":"Carefully heed the user's instructions and follow the user's will to the best of your ability.\nRespond using Markdown."
|
"content":"Carefully heed the user's instructions and follow the user's will to the best of your ability.\nRespond using Markdown."
|
||||||
},
|
|
||||||
{
|
|
||||||
"role":"user",
|
|
||||||
"content":"hello"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"model":"gpt-3.5-turbo-16k",
|
"model":"gpt-3.5-turbo-16k",
|
||||||
@ -2169,7 +2163,10 @@ boost::asio::awaitable<void> FreeGpt::ylokh(std::shared_ptr<Channel> ch, nlohman
|
|||||||
})";
|
})";
|
||||||
nlohmann::json request = nlohmann::json::parse(json_str, nullptr, false);
|
nlohmann::json request = nlohmann::json::parse(json_str, nullptr, false);
|
||||||
|
|
||||||
request["messages"][1]["content"] = prompt;
|
auto conversation = getConversationJson(json);
|
||||||
|
for (const auto& item : conversation)
|
||||||
|
request["messages"].push_back(item);
|
||||||
|
|
||||||
SPDLOG_INFO("{}", request.dump(2));
|
SPDLOG_INFO("{}", request.dump(2));
|
||||||
|
|
||||||
req.body() = request.dump();
|
req.body() = request.dump();
|
||||||
@ -2595,7 +2592,7 @@ boost::asio::awaitable<void> FreeGpt::aibn(std::shared_ptr<Channel> ch, nlohmann
|
|||||||
|
|
||||||
request["sign"] = signature;
|
request["sign"] = signature;
|
||||||
request["time"] = timestamp;
|
request["time"] = timestamp;
|
||||||
request["messages"][0]["content"] = prompt;
|
request["messages"] = getConversationJson(json);
|
||||||
|
|
||||||
auto str = request.dump();
|
auto str = request.dump();
|
||||||
SPDLOG_INFO("request : [{}]", str);
|
SPDLOG_INFO("request : [{}]", str);
|
||||||
@ -2628,3 +2625,81 @@ boost::asio::awaitable<void> FreeGpt::aibn(std::shared_ptr<Channel> ch, nlohmann
|
|||||||
}
|
}
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::asio::awaitable<void> FreeGpt::chatGptDuo(std::shared_ptr<Channel> ch, nlohmann::json json) {
|
||||||
|
co_await boost::asio::post(boost::asio::bind_executor(*m_thread_pool_ptr, boost::asio::use_awaitable));
|
||||||
|
|
||||||
|
boost::system::error_code err{};
|
||||||
|
ScopeExit _exit{[=] { boost::asio::post(ch->get_executor(), [=] { ch->close(); }); }};
|
||||||
|
auto prompt = json.at("meta").at("content").at("parts").at(0).at("content").get<std::string>();
|
||||||
|
|
||||||
|
CURLcode res;
|
||||||
|
CURL* curl = curl_easy_init();
|
||||||
|
if (!curl) {
|
||||||
|
auto error_info = std::format("curl_easy_init() failed:{}", curl_easy_strerror(res));
|
||||||
|
co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable));
|
||||||
|
ch->try_send(err, error_info);
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, "https://chatgptduo.com/");
|
||||||
|
auto request_data = urlEncode(std::format("prompt=('{}',)&search=('{}',)&purpose=ask", prompt, prompt));
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request_data.c_str());
|
||||||
|
|
||||||
|
struct Input {
|
||||||
|
std::shared_ptr<Channel> ch;
|
||||||
|
};
|
||||||
|
Input input{ch};
|
||||||
|
auto action_cb = [](void* contents, size_t size, size_t nmemb, void* userp) -> size_t {
|
||||||
|
boost::system::error_code err{};
|
||||||
|
auto input_ptr = static_cast<Input*>(userp);
|
||||||
|
std::string data{(char*)contents, size * nmemb};
|
||||||
|
auto& [ch] = *input_ptr;
|
||||||
|
boost::asio::post(ch->get_executor(), [=, data = std::move(data)] mutable {
|
||||||
|
nlohmann::json json = nlohmann::json::parse(data, nullptr, false);
|
||||||
|
if (json.is_discarded()) {
|
||||||
|
SPDLOG_ERROR("json parse error: [{}]", data);
|
||||||
|
ch->try_send(err, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (json.contains("answer")) {
|
||||||
|
auto str = json["answer"].get<std::string>();
|
||||||
|
ch->try_send(err, str);
|
||||||
|
} else {
|
||||||
|
ch->try_send(err, std::format("Invalid JSON: {}", json.dump()));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
return size * nmemb;
|
||||||
|
};
|
||||||
|
size_t (*action_fn)(void* contents, size_t size, size_t nmemb, void* userp) = action_cb;
|
||||||
|
curlEasySetopt(curl);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, action_fn);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &input);
|
||||||
|
|
||||||
|
struct curl_slist* headers = nullptr;
|
||||||
|
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
|
ScopeExit auto_exit{[=] {
|
||||||
|
curl_slist_free_all(headers);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}};
|
||||||
|
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
if (res != CURLE_OK) {
|
||||||
|
co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable));
|
||||||
|
auto error_info = std::format("curl_easy_perform() failed:{}", curl_easy_strerror(res));
|
||||||
|
ch->try_send(err, error_info);
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
int32_t response_code;
|
||||||
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
|
||||||
|
if (response_code != 200) {
|
||||||
|
co_await boost::asio::post(boost::asio::bind_executor(ch->get_executor(), boost::asio::use_awaitable));
|
||||||
|
ch->try_send(err, std::format("you http code:{}", response_code));
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <regex>
|
||||||
#include <semaphore>
|
#include <semaphore>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -38,8 +39,11 @@ void setEnvironment(auto& cfg) {
|
|||||||
if (!upper_http_proxy.empty())
|
if (!upper_http_proxy.empty())
|
||||||
cfg.http_proxy = std::move(upper_http_proxy);
|
cfg.http_proxy = std::move(upper_http_proxy);
|
||||||
}
|
}
|
||||||
if (auto [chat_path] = getEnv("CHAT_PATH"); !chat_path.empty())
|
if (auto [chat_path] = getEnv("CHAT_PATH"); !chat_path.empty()) {
|
||||||
cfg.chat_path = std::move(chat_path);
|
cfg.chat_path = std::move(chat_path);
|
||||||
|
}
|
||||||
|
if (cfg.chat_path.back() == '/')
|
||||||
|
cfg.chat_path.pop_back();
|
||||||
if (auto [port] = getEnv("PORT"); !port.empty())
|
if (auto [port] = getEnv("PORT"); !port.empty())
|
||||||
cfg.port = std::move(port);
|
cfg.port = std::move(port);
|
||||||
if (auto [host] = getEnv("HOST"); !host.empty())
|
if (auto [host] = getEnv("HOST"); !host.empty())
|
||||||
@ -67,6 +71,7 @@ std::string createIndexHtml(const std::string& file, const Config& cfg) {
|
|||||||
inja::Environment env;
|
inja::Environment env;
|
||||||
nlohmann::json data;
|
nlohmann::json data;
|
||||||
data["chat_id"] = createUuidString();
|
data["chat_id"] = createUuidString();
|
||||||
|
data["chat_path"] = cfg.chat_path;
|
||||||
if (!cfg.providers.empty()) {
|
if (!cfg.providers.empty()) {
|
||||||
data["model_list"] = cfg.providers;
|
data["model_list"] = cfg.providers;
|
||||||
} else {
|
} else {
|
||||||
@ -113,6 +118,8 @@ boost::asio::awaitable<void> startSession(boost::asio::ip::tcp::socket sock, Con
|
|||||||
co_await boost::beast::async_write(stream, std::move(rsp), use_nothrow_awaitable);
|
co_await boost::beast::async_write(stream, std::move(rsp), use_nothrow_awaitable);
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
auto assets_path = std::format("{}{}", cfg.chat_path, ASSETS_PATH);
|
||||||
|
SPDLOG_INFO("assets_path: [{}]", assets_path);
|
||||||
while (true) {
|
while (true) {
|
||||||
boost::beast::flat_buffer buffer;
|
boost::beast::flat_buffer buffer;
|
||||||
boost::beast::http::request<boost::beast::http::string_body> request;
|
boost::beast::http::request<boost::beast::http::string_body> request;
|
||||||
@ -142,15 +149,25 @@ boost::asio::awaitable<void> startSession(boost::asio::ip::tcp::socket sock, Con
|
|||||||
res.prepare_payload();
|
res.prepare_payload();
|
||||||
boost::beast::http::message_generator rsp = std::move(res);
|
boost::beast::http::message_generator rsp = std::move(res);
|
||||||
co_await boost::beast::async_write(stream, std::move(rsp), use_nothrow_awaitable);
|
co_await boost::beast::async_write(stream, std::move(rsp), use_nothrow_awaitable);
|
||||||
} else if (request.target().starts_with(ASSETS_PATH)) {
|
} else if (request.target().starts_with(assets_path)) {
|
||||||
std::string req_path{request.target()};
|
std::string req_path{request.target()};
|
||||||
req_path.erase(req_path.find(ASSETS_PATH), ASSETS_PATH.length());
|
SPDLOG_INFO("req_path: {}", req_path);
|
||||||
|
req_path.erase(req_path.find(assets_path), assets_path.length());
|
||||||
auto file = std::format("{}{}", cfg.client_root_path, req_path);
|
auto file = std::format("{}{}", cfg.client_root_path, req_path);
|
||||||
SPDLOG_INFO("load: {}", file);
|
SPDLOG_INFO("load: {}", file);
|
||||||
if (file.contains("chat.js")) {
|
if (file.contains("chat.js") || file.contains("site.webmanifest")) {
|
||||||
inja::Environment env;
|
inja::Environment env;
|
||||||
nlohmann::json data;
|
nlohmann::json data;
|
||||||
data["chat_path"] = cfg.chat_path;
|
if (file.contains("chat.js")) {
|
||||||
|
auto format_string = [](const std::string& str) {
|
||||||
|
std::regex pattern("/");
|
||||||
|
std::string replacement = "\\/";
|
||||||
|
return std::regex_replace(str, pattern, replacement);
|
||||||
|
};
|
||||||
|
data["chat_path"] = format_string(cfg.chat_path);
|
||||||
|
} else {
|
||||||
|
data["chat_path"] = cfg.chat_path;
|
||||||
|
}
|
||||||
auto chat_js_content = env.render_file(file, data);
|
auto chat_js_content = env.render_file(file, data);
|
||||||
boost::beast::http::response<boost::beast::http::string_body> res{boost::beast::http::status::ok,
|
boost::beast::http::response<boost::beast::http::string_body> res{boost::beast::http::status::ok,
|
||||||
request.version()};
|
request.version()};
|
||||||
@ -307,7 +324,7 @@ int main(int argc, char** argv) {
|
|||||||
ADD_METHOD("gpt-3.5-turbo-stream-openai", FreeGpt::openAi);
|
ADD_METHOD("gpt-3.5-turbo-stream-openai", FreeGpt::openAi);
|
||||||
ADD_METHOD("gpt-3.5-turbo-Aichat", FreeGpt::aiChat);
|
ADD_METHOD("gpt-3.5-turbo-Aichat", FreeGpt::aiChat);
|
||||||
ADD_METHOD("gpt-4-ChatgptAi", FreeGpt::chatGptAi);
|
ADD_METHOD("gpt-4-ChatgptAi", FreeGpt::chatGptAi);
|
||||||
ADD_METHOD("gpt-3.5-turbo-weWordle", FreeGpt::weWordle);
|
// ADD_METHOD("gpt-3.5-turbo-weWordle", FreeGpt::weWordle);
|
||||||
ADD_METHOD("gpt-3.5-turbo-acytoo", FreeGpt::acytoo);
|
ADD_METHOD("gpt-3.5-turbo-acytoo", FreeGpt::acytoo);
|
||||||
ADD_METHOD("gpt-3.5-turbo-stream-DeepAi", FreeGpt::deepAi);
|
ADD_METHOD("gpt-3.5-turbo-stream-DeepAi", FreeGpt::deepAi);
|
||||||
ADD_METHOD("gpt-3.5-turbo-stream-H2o", FreeGpt::h2o);
|
ADD_METHOD("gpt-3.5-turbo-stream-H2o", FreeGpt::h2o);
|
||||||
@ -316,7 +333,7 @@ int main(int argc, char** argv) {
|
|||||||
ADD_METHOD("gpt-4-turbo-stream-you", FreeGpt::you);
|
ADD_METHOD("gpt-4-turbo-stream-you", FreeGpt::you);
|
||||||
ADD_METHOD("gpt-3.5-turbo-AItianhu", FreeGpt::aiTianhu);
|
ADD_METHOD("gpt-3.5-turbo-AItianhu", FreeGpt::aiTianhu);
|
||||||
ADD_METHOD("gpt-3-stream-binjie", FreeGpt::binjie);
|
ADD_METHOD("gpt-3-stream-binjie", FreeGpt::binjie);
|
||||||
ADD_METHOD("gpt-3.5-turbo-stream-CodeLinkAva", FreeGpt::codeLinkAva);
|
// ADD_METHOD("gpt-3.5-turbo-stream-CodeLinkAva", FreeGpt::codeLinkAva);
|
||||||
ADD_METHOD("gpt-4-stream-ChatBase", FreeGpt::chatBase);
|
ADD_METHOD("gpt-4-stream-ChatBase", FreeGpt::chatBase);
|
||||||
ADD_METHOD("gpt-3.5-turbo-stream-aivvm", FreeGpt::aivvm);
|
ADD_METHOD("gpt-3.5-turbo-stream-aivvm", FreeGpt::aivvm);
|
||||||
ADD_METHOD("gpt-3.5-turbo-16k-stream-Ylokh", FreeGpt::ylokh);
|
ADD_METHOD("gpt-3.5-turbo-16k-stream-Ylokh", FreeGpt::ylokh);
|
||||||
@ -324,6 +341,7 @@ int main(int argc, char** argv) {
|
|||||||
ADD_METHOD("gpt-3.5-turbo-stream-GptGo", FreeGpt::gptGo);
|
ADD_METHOD("gpt-3.5-turbo-stream-GptGo", FreeGpt::gptGo);
|
||||||
ADD_METHOD("gpt-3.5-turbo-stream-AItianhuSpace", FreeGpt::aiTianhuSpace);
|
ADD_METHOD("gpt-3.5-turbo-stream-AItianhuSpace", FreeGpt::aiTianhuSpace);
|
||||||
ADD_METHOD("gpt-3.5-turbo-stream-Aibn", FreeGpt::aibn);
|
ADD_METHOD("gpt-3.5-turbo-stream-Aibn", FreeGpt::aibn);
|
||||||
|
ADD_METHOD("gpt-3.5-turbo-ChatgptDuo", FreeGpt::chatGptDuo);
|
||||||
|
|
||||||
IoContextPool pool{cfg.work_thread_num};
|
IoContextPool pool{cfg.work_thread_num};
|
||||||
pool.start();
|
pool.start();
|
||||||
|
@ -33,7 +33,7 @@ services:
|
|||||||
command: bash start-bot.sh
|
command: bash start-bot.sh
|
||||||
|
|
||||||
chat-gpt:
|
chat-gpt:
|
||||||
image: "fantasypeak/freegpt:latest"
|
image: "balshdocker/freegpt:latest"
|
||||||
container_name: "chat_gpt_chat_service"
|
container_name: "chat_gpt_chat_service"
|
||||||
hostname: "chat_service"
|
hostname: "chat_service"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
2064
poetry.lock
generated
2064
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@ python-telegram-bot = {version = "^20.5", extras=["ext"]}
|
|||||||
python-dotenv = "^1.0"
|
python-dotenv = "^1.0"
|
||||||
httpx = "^0.24"
|
httpx = "^0.24"
|
||||||
loguru = "^0.7"
|
loguru = "^0.7"
|
||||||
pydantic = "^2.3"
|
pydantic = "^2.4"
|
||||||
pydantic-settings = "^2.0.3"
|
pydantic-settings = "^2.0.3"
|
||||||
gunicorn = "^21.2"
|
gunicorn = "^21.2"
|
||||||
uvicorn = "^0.23"
|
uvicorn = "^0.23"
|
||||||
@ -21,33 +21,7 @@ orjson = "^3.9"
|
|||||||
sentry-sdk = "^1.31.0"
|
sentry-sdk = "^1.31.0"
|
||||||
SpeechRecognition = "^3.8"
|
SpeechRecognition = "^3.8"
|
||||||
pydub = "^0.25"
|
pydub = "^0.25"
|
||||||
|
|
||||||
websocket-client = "^1.6"
|
|
||||||
greenlet = "^2.0.2"
|
greenlet = "^2.0.2"
|
||||||
requests = "^2.31"
|
|
||||||
selenium = "^4.11"
|
|
||||||
tls-client = "^0.2"
|
|
||||||
pypasser = "^0.0.5"
|
|
||||||
names = "^0.3"
|
|
||||||
colorama = "^0.4"
|
|
||||||
curl_cffi = "0.5.7"
|
|
||||||
aiohttp = "^3.8.5"
|
|
||||||
flask = "^2.3"
|
|
||||||
flask_cors = "^4.0"
|
|
||||||
flask-babel = "^3.1"
|
|
||||||
streamlit = "^1.26"
|
|
||||||
fake-useragent = "^1.2"
|
|
||||||
twocaptcha = "^0.0.1"
|
|
||||||
pymailtm = "^1.1"
|
|
||||||
Levenshtein = "^0.21"
|
|
||||||
retrying = "^1.3"
|
|
||||||
mailgw_temporary_email = "^0.0.2"
|
|
||||||
pycryptodome = "^3.18"
|
|
||||||
random-password-generator = "^2.2"
|
|
||||||
numpy = "^1.25"
|
|
||||||
tornado = "^6.3"
|
|
||||||
PyExecJS = "^1.5"
|
|
||||||
browser_cookie3 = "^0.19"
|
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user