Skip to content

Commit

Permalink
Merge branch 'develop' into update
Browse files Browse the repository at this point in the history
  • Loading branch information
PandorasActorMS committed Oct 1, 2024
2 parents 216d1fa + 43f7a76 commit da313b8
Show file tree
Hide file tree
Showing 14 changed files with 453 additions and 187 deletions.
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.github
.git
.gitignore
.dockerignore
Caddyfile
compose.yml
docker-compose.yml
README.md
SECURITY.md
LICENSE.txt
Changelog.txt
59 changes: 59 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
on:
push:
pull_request:

name: CI build
jobs:
build:
name: CI build
runs-on: ubuntu-latest
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
permissions:
contents: read
packages: write
steps:

- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0



- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta-php
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-php
tags: |
type=schedule
type=ref,event=branch
type=ref,event=tag
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }}
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value={{branch}}-{{sha}}-{{date 'X'}},enable=${{ github.event_name != 'pull_request' && !contains(github.ref, 'refs/tags/') }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile.php
push: ${{ github.event_name != 'pull_request' && github.actor != 'dependabot[bot]'}}
tags: ${{ steps.meta-php.outputs.tags }}
labels: ${{ steps.meta-php.outputs.labels }}
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
.env
.DS_Store
.DS_Store
compose.yml
docker-compose.yml
Caddyfile
.vscode/
20 changes: 20 additions & 0 deletions Dockerfile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM php:8.3-fpm-alpine AS BUILD
COPY . /var/www/html/
ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/download/2.2.16/install-php-extensions /usr/local/bin/
RUN apk add --no-cache git libzip-dev zip \
&& docker-php-ext-install zip \
&& cd /var/www/html \
&& chmod +x composer_install.sh && ./composer_install.sh \
&& mv composer.phar /usr/local/bin/composer \
&& composer install --no-cache \
&& install-php-extensions pdo pdo_pgsql

FROM php:8.3-fpm-alpine
WORKDIR /var/www/html
COPY --from=BUILD /var/www/html /var/www/html
# pdo pdo_pgsql dependencies
COPY --from=BUILD /usr/lib/libpgtypes.so.* /usr/lib/
COPY --from=BUILD /usr/lib/libpq.so.* /usr/lib/
COPY --from=BUILD /usr/lib/libecpg.so.* /usr/lib
COPY --from=BUILD /usr/local/etc/php/conf.d/docker-php-ext-pdo_pgsql.ini /usr/local/etc/php/conf.d/
COPY --from=BUILD /usr/local/lib/php/extensions /usr/local/lib/php/extensions
16 changes: 11 additions & 5 deletions private/app/php/auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ function handleLdapLogin($username, $password){

// *** ACTIVATES TEST ACCESS ***
// Please set a unique test username and password in .env
if(isset($env['TESTUSER']) && isset($env['TESTPASSWORD']) &&
!empty($env['TESTUSER']) && !empty($env['TESTPASSWORD']) &&
$username == $env['TESTUSER'] && $password == $env['TESTPASSWORD']) {
$_SESSION['username'] = $env['TESTUSER'];
if(((isset($env) ? strtolower($env["TEST"]) : strtolower(getenv("TEST"))) === "true") &&
!empty(getenv('TESTUSER')) && !empty(getenv('TESTPASSWORD')) &&
$username == getenv('TESTUSER') && $password == getenv('TESTPASSWORD')) {
$_SESSION['username'] = getenv('TESTUSER');
$_SESSION['employeetype'] = "Tester";
return true;
}
Expand Down Expand Up @@ -141,7 +141,13 @@ function handleLdapLogin($username, $password){

// filter username to prevent unwanted inputs.
$username = filter_var($_POST["account"], FILTER_UNSAFE_RAW);
$username = ldap_escape($username, "", LDAP_ESCAPE_FILTER);
if (!((isset($env) ? strtolower($env["TEST"]) : strtolower(getenv("TEST"))) === "true")) {
$username = ldap_escape($username, "", LDAP_ESCAPE_FILTER);
}





// Use hashed password if LDAP Server is configured accordingly.
// $password = password_hash($_POST["password"], PASSWORD_DEFAULT);
Expand Down
107 changes: 107 additions & 0 deletions private/app/php/stream-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
// Read the request payload from the client
$requestPayload = file_get_contents('php://input');

$requestPayload = json_decode($requestPayload, true);
$requestPayload['stream_options']['include_usage'] = true;
$requestPayload = json_encode($requestPayload);
if ((isset($env) ? strtolower($env['TOKEN_DB']) : strtolower(getenv('TOKEN_DB'))) == "true") {
check_token_limit();
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_POST, 1);
Expand All @@ -48,6 +55,10 @@
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) {
if (strtolower(isset($env) ? $env['TOKEN_DB'] : getenv('TOKEN_DB')) == "true") {
get_tokens($data);
}

echo $data;
if (ob_get_level() > 0) {
ob_flush();
Expand All @@ -64,3 +75,99 @@

curl_close($ch);


function get_tokens($data){
$jsonstrings= explode("data: ", $data);
foreach ($jsonstrings as &$jsonstring) {
$json = json_decode($jsonstring, true);
if (!isset($json) || $json['usage'] == null) {
continue;
}

$prompt_tokens = $json['usage']['prompt_tokens'];
$completion_tokens = $json['usage']['completion_tokens'];
$total_tokens = $json['usage']['total_tokens'];

$host = getenv("DB_HOST");
$db = getenv("DB_DB");
$table = getenv('DB_TABLE');
$user = getenv("DB_USER");
$pass = getenv("DB_PASS");
$port = getenv("DB_PORT");
$dsn = "pgsql:host=$host;port=$port;dbname=$db";
try{
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO $table (username,datum,prompt_tokens,completion_tokens,total_tokens,model) VALUES(:username,:datum,:prompt,:completion,:total,:model) ON CONFLICT (username,datum,model) DO UPDATE SET prompt_tokens = $table.prompt_tokens + EXCLUDED.prompt_tokens, completion_tokens = $table.completion_tokens + EXCLUDED.completion_tokens, total_tokens = $table.total_tokens + EXCLUDED.total_tokens, model = $table.model;";
$stmt=$pdo->prepare($sql);
$stmt->bindParam(':username',$username);
$stmt->bindParam(':datum',$datum);
$stmt->bindParam(':prompt',$prompt);
$stmt->bindParam(':completion',$completion);
$stmt->bindParam(':total',$total);
$stmt->bindParam(':model',$model);

$username = $_SESSION['username'];
$datum = date("Y-m-d");
$prompt = $prompt_tokens;
$completion = $completion_tokens;
$total = $total_tokens;
global $requestPayload;
$model = json_decode($requestPayload, true)['model'];
$stmt->execute();

} catch (PDOException $e) {
error_log($e->getMessage(),0);
}
}
unset($jsonstring);
}

function check_token_limit(){
$max_tokens = getenv("TOKEN_LIMIT");
if ($max_tokens <= 0) {
return;
}

$host = getenv("DB_HOST");
$db = getenv("DB_DB");
$table = getenv('DB_TABLE');
$user = getenv("DB_USER");
$pass = getenv("DB_PASS");
$port = getenv("DB_PORT");
$dsn = "pgsql:host=$host;port=$port;dbname=$db";

try {
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT SUM(total_tokens) AS total_tokens FROM $table WHERE datum >= (:datum ::date - INTERVAL '2 day')::date AND username = :username GROUP BY username;";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':username', $username);
$stmt->bindParam(':datum', $datum);
$username = $_SESSION['username'];
$datum = date("Y-m-d");
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);

if ($result && $result['total_tokens'] >= $max_tokens) {
$message = $_SESSION['translation']['tokenUsedMessage'];
$response = [
'error' => true,
'choices' => [['delta' => ['content' => $message]]]
];

echo "data: " . json_encode($response) . "\n\n";

if (ob_get_level() > 0) {
ob_flush();
}
flush();

exit;
}
} catch (PDOException $e) {
error_log($e->getMessage());
exit;
}

}
104 changes: 104 additions & 0 deletions private/app/php/user_feedback.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<script>
//#region USER FEEDBACK
//----------------------------------------------------------------------------------------//
//save users feedback on server.
//other users can up or downvote othes feedback
async function send_feedback(){
const messagesElement = document.querySelector(".messages");
const inputField = document.querySelector(".userpost-field");

if(inputField.value == ''){
return;
}

let message = {};
message.role = '<?= htmlspecialchars($_SESSION['username']) ?>';
message.content = inputField.value.trim();

// const feedback_send = "../private/app/php/feedback_send.php";
const feedback_send = "api/feedback_send"
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

fetch(feedback_send, {
method: 'POST',
headers: {
'Content-Type': 'application/json', // Set content type to application/json
'X-CSRF-TOKEN': csrfToken, // Include CSRF token in the request headers
},
body: JSON.stringify({message: message}),
})
.then(response => response.json())
.then(data => {
//UPDATE NEW TOKEN
document.querySelector('meta[name="csrf-token"]').setAttribute('content', data.csrf_token);

if(data.success){
load(document.querySelector("#feedback"), 'feedback_loader.php');
inputField.value = "";
}
})
.catch(error => console.error(error));
}

function SubmitVote(element, action) {
if (localStorage.getItem(element.dataset.id)) {
return;
}

const pureId = element.dataset.id.replace('.json', ''); // assuming all IDs end with '.json'
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
const submit_vote = "api/submit_vote";

fetch(submit_vote, {
method: 'POST',
headers: {
'Content-Type': 'application/json', // Set content type to application/json
'X-CSRF-TOKEN': csrfToken, // Include CSRF token in the request headers
},
body: JSON.stringify({ id: pureId, action: action }), // Send the action and CSRF token in the request body
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {

document.querySelector('meta[name="csrf-token"]').setAttribute('content', data.csrf_token);
if(data.success){

// Update the UI accordingly
if (action === "upvote") {
element.querySelector("span").textContent = data.content.up || 0; // Assuming 'data.up' contains the updated upvote count
}
if (action === "downvote") {
element.querySelector("span").textContent = data.content.down || 0; // Assuming 'data.down' contains the updated downvote count
}
}
})
.catch(error => {
console.error('Fetch error:', error);
});
localStorage.setItem(element.dataset.id, "true");

voteHover();
}

async function voteHover(){
let messages = document.querySelectorAll(".message");

messages.forEach((message)=>{
let voteButtons = message.querySelectorAll(".vote")

voteButtons.forEach((voteButton)=>{
if(localStorage.getItem(voteButton.dataset.id)){
voteButton.classList.remove("vote-hover");
}else{
voteButton.classList.add("vote-hover");
}
})
})
}
//#endregion
</script>
Loading

0 comments on commit da313b8

Please sign in to comment.