From 962b0c33b84f1e4f058c413281561daf3788aea2 Mon Sep 17 00:00:00 2001 From: Gerard Hickey Date: Tue, 13 Feb 2024 00:33:11 -0500 Subject: [PATCH] Add GitHub Actions workflow to automate releases (#40) * Added beginnings of package building code * chore: create release CI job * chore: add documentation section to changelog * chore: make build-meshchat-package a reusable workflow * chore: add build packages to release * fix: update-version.sh can now be told version to set * chore(ci): convert meshchat-api build to reusable workflow * chore(ci): set release to only work on release branch Signed-off-by: Gerard Hickey --- .../workflows/build-meshchat-api-package.yaml | 33 +- .github/workflows/build-meshchat-package.yaml | 40 +- .github/workflows/release-meshchat.yaml | 72 ++++ .release-it.yaml | 6 +- README.md | 2 + meshchat | 22 +- package/ipk-build | 126 ++++++ package/update-version.sh | 44 +- www/chat.js | 398 ++++++++++++++++++ 9 files changed, 683 insertions(+), 60 deletions(-) create mode 100644 .github/workflows/release-meshchat.yaml create mode 100755 package/ipk-build diff --git a/.github/workflows/build-meshchat-api-package.yaml b/.github/workflows/build-meshchat-api-package.yaml index b48909e..e11f448 100644 --- a/.github/workflows/build-meshchat-api-package.yaml +++ b/.github/workflows/build-meshchat-api-package.yaml @@ -1,16 +1,29 @@ name: Build MeshChat API Package -on: push -env: - IPK_DIR: package/meshchat-api-ipkg +on: + workflow_call: + inputs: + build_version: + required: true + type: string + build_dir: + required: true + type: string + jobs: create-meshchat-api-package: runs-on: ubuntu-latest + # container: + # image: registry.gitlab.com/wt0f/gitlab-runner-images/shell:latest steps: - - uses: actions/checkout@v3 - - run: package/populate-meshchat-api-fs.sh $IPK_DIR - - run: package/update-version.sh $IPK_DIR - - run: package/ipk-build.sh $IPK_DIR - - uses: actions/upload-artifact@v3 + - uses: actions/checkout@v4 + - run: echo ${{ inputs.build_version }} > VERSION + - run: package/populate-meshchat-api-fs.sh ${{ inputs.build_dir }} + - run: package/update-version.sh ${{ inputs.build_dir }} + - run: package/ipk-build.sh ${{ inputs.build_dir }} + - id: detect-package-file + run: echo "file=$(ls -1 meshchat_*.ipk)" >> $GITHUB_OUTPUT + - run: echo "${{ steps.detect-package-file.outputs.file }}" + - uses: actions/upload-artifact@v4 with: - name: meshchat-api - path: meshchat-api_* \ No newline at end of file + name: ${{ steps.detect-package-file.outputs.file }} + path: ${{ steps.detect-package-file.outputs.file }} diff --git a/.github/workflows/build-meshchat-package.yaml b/.github/workflows/build-meshchat-package.yaml index 6b4c713..2d4f86e 100644 --- a/.github/workflows/build-meshchat-package.yaml +++ b/.github/workflows/build-meshchat-package.yaml @@ -1,18 +1,34 @@ name: Build MeshChat Package -on: push -env: - IPK_DIR: package/meshchat-ipkg +on: + workflow_call: + inputs: + build_version: + required: true + type: string + build_dir: + required: true + type: string + jobs: create-meshchat-package: runs-on: ubuntu-latest + # container: + # image: registry.gitlab.com/wt0f/gitlab-runner-images/shell:latest + outputs: + package_file: ${{ steps.detect-package-file.outputs.file }} steps: - - uses: actions/checkout@v3 - - run: package/populate-meshchat-fs.sh $IPK_DIR - - run: package/update-version.sh $IPK_DIR - - run: package/ipk-build.sh $IPK_DIR - - uses: actions/upload-artifact@v3 + - uses: actions/checkout@v4 + # - run: info "Populating the filesystem with MeshChat files" + - run: echo ${{ inputs.build_version }} > VERSION + - run: package/populate-meshchat-fs.sh ${{ inputs.build_dir }} + # - run: info "Updating version numbers to " + - run: package/update-version.sh ${{ inputs.build_dir }} + # - run: info "Packing up MeshChat files" + - run: package/ipk-build.sh ${{ inputs.build_dir }} + - id: detect-package-file + run: echo "file=$(ls -1 meshchat_*.ipk)" >> $GITHUB_OUTPUT + - run: echo "${{ steps.detect-package-file.outputs.file }}" + - uses: actions/upload-artifact@v4 with: - name: meshchat - path: | - meshchat_*.ipk - VERSION \ No newline at end of file + name: ${{ steps.detect-package-file.outputs.file }} + path: ${{ steps.detect-package-file.outputs.file }} diff --git a/.github/workflows/release-meshchat.yaml b/.github/workflows/release-meshchat.yaml new file mode 100644 index 0000000..0da192d --- /dev/null +++ b/.github/workflows/release-meshchat.yaml @@ -0,0 +1,72 @@ +name: Release MeshChat Package +on: + pull_request: + types: [closed] + branches: [release] + +jobs: + create-release: + runs-on: ubuntu-latest + # container: + # image: registry.gitlab.com/wt0f/gitlab-runner-images/node:latest + outputs: + build_version: ${{ steps.detect_version.outputs.build_version }} + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_IT_TOKEN }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: git config + run: | + git config user.name "${GITHUB_ACTOR}" + git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" + - run: npm install -g release-it @release-it/conventional-changelog @commitlint/config-conventional @commitlint/cli auto-changelog + - id: detect_version + run: echo "build_version=$(npx release-it --release-version)" >> $GITHUB_OUTPUT + - run: npx release-it -VV --ci + - run: git checkout master + - run: git rebase release + - run: git push + + build-meshchat-package: + needs: create-release + uses: + ./.github/workflows/build-meshchat-package.yaml + with: + build_version: ${{ needs.create-release.outputs.build_version }} + build_dir: package/meshchat-ipkg + + build-meshchat-api-package: + needs: create-release + uses: + ./.github/workflows/build-meshchat-api-package.yaml + with: + build_version: ${{ needs.create-release.outputs.build_version }} + build_dir: package/meshchat-ipkg + + add-meshchat-package-to-release: + needs: + - build-meshchat-package + - build-meshchat-api-package + # container: + # image: registry.gitlab.com/wt0f/gitlab-runner-images/node:latest + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + - run: git pull + - run: npm install -g release-it @release-it/conventional-changelog @commitlint/config-conventional @commitlint/cli auto-changelog + - uses: actions/download-artifact@v4 + with: + name: ${{ needs.release_meshchat_package.outputs.package_file }} + path: ${{ needs.release_meshchat_package.outputs.package_file }} + - run: | + for file in *.ipk; do + echo "uploading $file" + npx release-it --ci --no-increment --no-git --no-npm --github.update=true --github.assets=$file + done + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_IT_TOKEN }} diff --git a/.release-it.yaml b/.release-it.yaml index ea9847d..66b6baa 100644 --- a/.release-it.yaml +++ b/.release-it.yaml @@ -6,14 +6,13 @@ git: tagName: "v${version}" tagAnnotation: "Automated release: ${version}" push: true - #requireBranch: release + requireBranch: release requireCommits: true changelog: "npx auto-changelog --stdout --commit-limit false" github: release: true releaseName: "v${version}" - assets: ["*.ipk", "*.deb"] npm: publish: false @@ -28,4 +27,5 @@ plugins: section: Features - type: fix section: Bug Fixes - + - tyep: docs + section: Documentation diff --git a/README.md b/README.md index 36f2e06..392db44 100644 --- a/README.md +++ b/README.md @@ -56,3 +56,5 @@ released in v2.9. If you are looking for a feature to be implemented or find a bug, please be sure to [create an issue](https://github.com/hickey/meshchat/issues/new) in the project so that it can be prioritized. + + diff --git a/meshchat b/meshchat index b32c506..0a2c79b 100755 --- a/meshchat +++ b/meshchat @@ -93,9 +93,9 @@ function send_message() print("\r") local message = query.message:gsub("\n", "\\n"):gsub('"', '\\"'):gsub("\t", " ") - local id = query.id or hash(); + local epoch = os.time() - if query.epoch and tonumber(query.epoch) > epoch then + if tonumber(query.epoch) > epoch then epoch = query.epoch end @@ -106,7 +106,7 @@ function send_message() release_lock() die("Cannot send message") end - f:write(id .. "\t" .. epoch .. "\t" .. message .. "\t" .. query.call_sign .. "\t" .. node_name() .. "\t" .. platform .. "\t" .. query.channel .. "\n") + f:write(hash() .. "\t" .. epoch .. "\t" .. message .. "\t" .. query.call_sign .. "\t" .. node_name() .. "\t" .. platform .. "\t" .. query.channel .. "\n") f:close() sort_and_trim_db() @@ -133,7 +133,6 @@ function messages() local node = node_name() - -- read in message DB and parse the contents local messages = {} for line in io.lines(messages_db_file) do @@ -153,8 +152,6 @@ function messages() if tonumber(query.epoch) and query.call_sign then local users = {} - - -- read the users status file if nixio.fs.stat(local_users_status_file) then for line in io.lines(local_users_status_file) do @@ -165,14 +162,11 @@ function messages() end end - -- set the timestamp local epoch = os.time() if tonumber(query.epoch) > epoch then epoch = query.epoch end - -- rewrite user status file updating the timestamp for requesting call sign - -- query.id is the meshchat_id local f = io.open(local_users_status_file, "w") if f then local found_user = false @@ -194,7 +188,6 @@ function messages() release_lock() - -- order messages according to time table.sort(messages, function(a, b) return a.epoch > b.epoch end) output:write(luci.jsonc.stringify(messages)) @@ -359,7 +352,7 @@ function local_files_raw() for file in nixio.fs.dir(local_files_dir) do local stat = nixio.fs.stat(local_files_dir .. "/" .. file) - f:write(file .. "\t" .. name .. "\t" .. stat.size .. "\t" .. stat.mtime .. "\t" .. platform .. "\n") + f:write(file .. "\t" .. name .. "\t" .. stat.size .. "\t" .. stat.mtime .. platform .. "\n") end f:close() @@ -474,7 +467,7 @@ end function messages_version_ui() print("Content-type: application/json\r") print("\r") - + print(string.format([[{"messages_version":%s}]], get_messages_db_version())) get_lock() @@ -494,7 +487,6 @@ function messages_version_ui() epoch = query.epoch end - -- TODO refactor here and messages function into a single code block local f = io.open(local_users_status_file, "w") if f then local found_user = false @@ -519,7 +511,7 @@ end function hosts() print("Content-type: application/json\r") print("\r") - + local node = node_name() local hosts = {} for line in io.lines("/var/dhcp.leases") @@ -570,7 +562,7 @@ end function hosts_raw() print("Content-type: application/json\r") print("\r") - + local hosts = {} for line in io.lines("/var/dhcp.leases") do diff --git a/package/ipk-build b/package/ipk-build new file mode 100755 index 0000000..9960e77 --- /dev/null +++ b/package/ipk-build @@ -0,0 +1,126 @@ +#!/bin/sh +# ipkg-build -- construct a .ipk from a directory +# Carl Worth +# based on a script by Steve Redler IV, steve@sr-tech.com 5-21-2001 +set -e + +ipkg_extract_value() { + sed -e "s/^[^:]*:[[:space:]]*//" +} + +required_field() { + field=$1 + + value=`grep "^$field:" < $CONTROL/control | ipkg_extract_value` + if [ -z "$value" ]; then + echo "ipkg-build: Error: $CONTROL/control is missing field $field" ; + PKG_ERROR=1 + fi + echo $value +} + +pkg_appears_sane() { + local pkg_dir=$1 + + local owd=`pwd` + cd $pkg_dir + + PKG_ERROR=0 + if [ ! -f "$CONTROL/control" ]; then + echo "ipkg-build: Error: Control file $pkg_dir/$CONTROL/control not found." + cd $owd + return 1 + fi + + pkg=`required_field Package` + version=`required_field Version` + arch=`required_field Architecture` + required_field Maintainer >/dev/null + required_field Description >/dev/null + + if echo $pkg | grep '[^a-z0-9.+-]'; then + echo "ipkg-build: Error: Package name $name contains illegal characters, (other than [a-z0-9.+-])" + PKG_ERROR=1; + fi + + local bad_fields=`sed -ne 's/^\([^[:space:]][^:[:space:]]\+[[:space:]]\+\)[^:].*/\1/p' < $CONTROL/control | sed -e 's/\\n//'` + if [ -n "$bad_fields" ]; then + bad_fields=`echo $bad_fields` + echo "ipkg-build: Error: The following fields in $CONTROL/control are missing a ':'" + echo " $bad_fields" + echo "ipkg-build: This may be due to a missing initial space for a multi-line field value" + PKG_ERROR=1 + fi + + for script in $CONTROL/preinst $CONTROL/postinst $CONTROL/prerm $CONTROL/postrm; do + if [ -f $script -a ! -x $script ]; then + echo "ipkg-build: Error: package script $script is not executable" + PKG_ERROR=1 + fi + done + + if [ -f $CONTROL/conffiles ]; then + for cf in `cat $CONTROL/conffiles`; do + if [ ! -f ./$cf ]; then + echo "ipkg-build: Error: $CONTROL/conffiles mentions conffile $cf which does not exist" + PKG_ERROR=1 + fi + done + fi + + cd $owd + return $PKG_ERROR +} + +### +# ipkg-build "main" +### + +case $# in +1) + dest_dir=. + ;; +2) + dest_dir=$2 + ;; +*) + echo "Usage: ipkg-build []" ; + exit 1 + ;; +esac + +pkg_dir=$1 + +if [ ! -d $pkg_dir ]; then + echo "ipkg-build: Error: Directory $pkg_dir does not exist" + exit 1 +fi + +# CONTROL is second so that it takes precedence +CONTROL= +[ -d $pkg_dir/DEBIAN ] && CONTROL=DEBIAN +[ -d $pkg_dir/CONTROL ] && CONTROL=CONTROL +if [ -z "$CONTROL" ]; then + echo "ipkg-build: Error: Directory $pkg_dir has no CONTROL subdirectory." + exit 1 +fi + +if ! pkg_appears_sane $pkg_dir; then + echo "Please fix the above errors and try again." + exit 1 +fi + +tmp_dir=$dest_dir/IPKG_BUILD.$$ +mkdir $tmp_dir + +tar -C $pkg_dir -czf $tmp_dir/data.tar.gz . --exclude=$CONTROL +tar -C $pkg_dir/$CONTROL -czf $tmp_dir/control.tar.gz . + +echo "2.0" > $tmp_dir/debian-binary + +pkg_file=$dest_dir/${pkg}_${version}_${arch}.ipk +tar -C $tmp_dir -czf $pkg_file debian-binary data.tar.gz control.tar.gz +rm $tmp_dir/debian-binary $tmp_dir/data.tar.gz $tmp_dir/control.tar.gz +rmdir $tmp_dir + +echo "Packaged contents of $pkg_dir into $pkg_file" diff --git a/package/update-version.sh b/package/update-version.sh index 5c2f2c8..9e169c8 100755 --- a/package/update-version.sh +++ b/package/update-version.sh @@ -6,28 +6,32 @@ IPK_DIR=$1 -if [[ "${GITHUB_REF_TYPE}" == 'tag' ]]; then - # ideally should only get version tags (i.e. 'v' followed by a number) - if [[ "${GITHUB_REF_NAME}" =~ ^v[0-9].* ]]; then - version="${GITHUB_REF_NAME#v}" - fi -elif [[ -n "${CI_COMMIT_TAG}" ]]; then - # ideally should only get version tags (i.e. 'v' followed by a number) - if [[ "${CI_COMMIT_TAG}" =~ ^v[0-9].* ]]; then - version="${CI_COMMIT_TAG#v}" - fi +if [[ -f VERSION ]]; then + version=$(cat VERSION) else - # branch gets date code-branch_name-commit - date=$(date +%Y%m%d) - branch=$(git rev-parse --abbrev-ref HEAD) - # maybe a detached head, so check common vars for branch name - if [[ -n "${CI_COMMIT_REF_NAME}" ]]; then - branch="${CI_COMMIT_REF_NAME}" - elif [[ -n "${GITHUB_REF_NAME}" ]]; then - branch="${GITHUB_REF_NAME}" + if [[ "${GITHUB_REF_TYPE}" == 'tag' ]]; then + # ideally should only get version tags (i.e. 'v' followed by a number) + if [[ "${GITHUB_REF_NAME}" =~ ^v[0-9].* ]]; then + version="${GITHUB_REF_NAME#v}" + fi + elif [[ -n "${CI_COMMIT_TAG}" ]]; then + # ideally should only get version tags (i.e. 'v' followed by a number) + if [[ "${CI_COMMIT_TAG}" =~ ^v[0-9].* ]]; then + version="${CI_COMMIT_TAG#v}" + fi + else + # branch gets date code-branch_name-commit + date=$(date +%Y%m%d) + branch=$(git rev-parse --abbrev-ref HEAD) + # maybe a detached head, so check common vars for branch name + if [[ -n "${CI_COMMIT_REF_NAME}" ]]; then + branch="${CI_COMMIT_REF_NAME}" + elif [[ -n "${GITHUB_REF_NAME}" ]]; then + branch="${GITHUB_REF_NAME}" + fi + commit=$(git rev-parse --short HEAD) + version="${date}-${branch}-${commit}" fi - commit=$(git rev-parse --short HEAD) - version="${date}-${branch}-${commit}" fi # write the version to a VERSION file diff --git a/www/chat.js b/www/chat.js index 9e616d0..0569882 100644 --- a/www/chat.js +++ b/www/chat.js @@ -1,3 +1,4 @@ +<<<<<<< HEAD var meshchat_id; var last_messages_update = epoch(); var call_sign = 'NOCALL'; @@ -255,3 +256,400 @@ function load_users() { users_updating = false; }); } +||||||| parent of fff9980 (Initial pass at reorganization) +======= +var last_messages_update = epoch(); +var call_sign = 'NOCALL'; +var meshchat_id; +var peer; +var mediaConnection; +var enable_video = 0; +var messages_updating = false; +var users_updating = false; +var messages = []; +var channel_filter = ''; +var messages_version = 0; +var alert = new Audio('alert.mp3'); +var message_db_version = 0; +var pending_message_db_version = 0; +var search_filter = ''; + +$(function() { + meshchat_init(); +}); + +function monitor_last_update() { + var secs = epoch() - last_messages_update; + $('#last-update').html('Updated: ' + secs + ' seconds ago'); +} + +function start_chat() { + //$('#logout').html('Logout ' + call_sign); + load_messages(); + load_users(); + monitor_last_update(); + setInterval(function() { + load_messages() + }, 15000); + setInterval(function() { + load_users() + }, 15000); + setInterval(function() { + monitor_last_update() + }, 2500); +} + +function meshchat_init() { + $('#message').val(''); + meshchat_id = Cookies.get('meshchat_id'); + if (meshchat_id == undefined) { + Cookies.set('meshchat_id', make_id()); + meshchat_id = Cookies.get('meshchat_id'); + } + //console.log(meshchat_id); + $('#submit-message').on('click', function(e) { + e.preventDefault(); + if ($('#message').val().length == 0) return; + + ohSnapX(); + + $(this).prop("disabled", true); + $('#message').prop("disabled", true); + $(this).html('
'); + + var channel = $('#send-channel').val(); + + if ($('#new-channel').val() != '') { + channel = $('#new-channel').val(); + $('#send-channel').val('Everything'); + } + + $.ajax({ + url: '/cgi-bin/meshchat', + type: "POST", + tryCount : 0, + retryLimit : 3, + cache: false, + timeout: 5000, + data: + { + action: 'send_message', + message: $('#message').val(), + call_sign: call_sign, + epoch: epoch(), + channel: channel + }, + dataType: "json", + context: this, + success: function(data, textStatus, jqXHR) + { + if (data.status == 500) { + ohSnap('Error sending message: ' + data.response, 'red', {time: '30000'}); + } else { + $('#message').val(''); + ohSnap('Message sent', 'green'); + load_messages(); + channel_filter = channel; + $('#new-channel').val(''); + $('#new-channel').hide(); + $('#send-channel').show(); + } + }, + error: function(jqXHR, textStatus, errorThrown) + { + if (textStatus == 'timeout') { + this.tryCount++; + if (this.tryCount <= this.retryLimit) { + //try again + $.ajax(this); + return; + } + ohSnap('Error sending message: ' + textStatus, 'red', {time: '30000'}); + } + }, + complete: function(jqXHR, textStatus) { + $(this).prop("disabled", false); + $('#message').prop("disabled", false); + $(this).html('Send'); + } + }); + }); + + $('#submit-call-sign').on('click', function(e) { + e.preventDefault(); + if ($('#call-sign').val().length == 0) return; + call_sign = $('#call-sign').val().toUpperCase(); + Cookies.set('meshchat_call_sign', call_sign); + $('#call-sign-container').addClass('hidden'); + $('#chat-container').removeClass('hidden'); + $('#callsign').html('Call Sign: ' + Cookies.get('meshchat_call_sign')); + start_chat(); + }); + + $('#channels').on('change', function() { + channel_filter = this.value; + process_messages(); + }); + + $('#search').keyup(function() { + //console.log(this.value); + search_filter = this.value; + process_messages(); + }); + + $('#message-expand').on('click', function(e) { + $('#message-panel').toggleClass('message-panel-collapse'); + $('#message-panel-body').toggleClass('message-panel-body-collapse'); + $('#users-panel').toggleClass('users-panel-collapse'); + $('#users-panel-body').toggleClass('users-panel-body-collapse'); + }); + + $('#send-channel').on('change', function() { + if (this.value == "Add New Channel") { + $('#new-channel').show(); + $(this).hide(); + } + }); + + $('#message').keydown(function (e) { + if ((event.keyCode == 10 || event.keyCode == 13) && event.ctrlKey) { + $("#submit-message").trigger( "click" ); + } + }); + + var cookie_call_sign = Cookies.get('meshchat_call_sign'); + if (cookie_call_sign == undefined) { + $('#call-sign-container').removeClass('hidden'); + } else { + $('#call-sign-container').addClass('hidden'); + $('#chat-container').removeClass('hidden'); + call_sign = cookie_call_sign; + start_chat(); + } +} + +function load_messages() { + if (messages_updating == true) return; + + messages_updating = true; + + $.ajax({ + url: '/cgi-bin/meshchat?action=messages_version_ui&call_sign=' + call_sign + '&id=' + meshchat_id + '&epoch=' + epoch(), + type: "GET", + dataType: "json", + context: this, + cache: false, + success: function(data, textStatus, jqXHR) + { + if (data == null) { + messages_updating = false; + return; + } + + if (data.messages_version != message_db_version) { + pending_message_db_version = data.messages_version; + fetch_messages(); + } else { + messages_updating = false; + last_messages_update = epoch(); + } + }, + error: function(jqXHR, textStatus, errorThrown) + { + messages_updating = false; + }, + complete: function(jqXHR, textStatus) { + + } + }); + +} + +function fetch_messages() { + $.ajax({ + url: '/cgi-bin/meshchat?action=messages&call_sign=' + call_sign + '&id=' + meshchat_id + '&epoch=' + epoch(), + type: "GET", + dataType: "json", + context: this, + cache: false, + success: function(data, textStatus, jqXHR) + { + if (data == null) return; + + messages = data; + + process_messages(); + last_messages_update = epoch(); + message_db_version = pending_message_db_version; + }, + complete: function(jqXHR, textStatus) { + //console.log( "messages complete" ); + messages_updating = false; + } + }); +} + +function process_messages() { + var html = ''; + + var cur_send_channel = $("#send-channel").val(); + + $('#send-channel') + .find('option') + .remove() + .end(); + + $('#channels') + .find('option') + .remove() + .end(); + + var channels = {}; + + var total = 0; + + var search = search_filter.toLowerCase(); + + for (var i = 0; i < messages.length; i++) { + var row = ''; + var date = new Date(0); + date.setUTCSeconds(messages[i].epoch); + var message = messages[i].message; + message = message.replace(/(\r\n|\n|\r)/g, "
"); + + var id = parseInt(messages[i].id, 16); + total += id; + + var formated_date = format_date(date); + + if (search != '') { + //console.log(search); + //console.log(message.toLowerCase()); + if (message.toLowerCase().search(search) == -1 && + messages[i].call_sign.toLowerCase().search(search) == -1 && + messages[i].node.toLowerCase().search(search) == -1 && + formated_date.toLowerCase().search(search) == -1) { + continue; + } + } + + if (messages[i].channel == null) { + messages[i].channel = ""; + } + + row += ''; + row += '' + formated_date + ''; + row += '' + message + ''; + row += '' + messages[i].call_sign + ''; + row += '' + messages[i].channel + ''; + if (messages[i].platform == 'node') { + row += '' + messages[i].node + ''; + } else { + row += '' + messages[i].node + ''; + } + row += ''; + + if (messages[i].channel != "" && !channels.hasOwnProperty(messages[i].channel)) { + channels[messages[i].channel] = 1; + } + + if (channel_filter != '') { + if (channel_filter == messages[i].channel) html += row; + } else { + html += row; + } + } + + if (messages_version != 0) { + if (total != messages_version) { + alert.play(); + } + } + + messages_version = total; + + $('#message-table').html(html); + + $('#send-channel') + .append($("") + .attr("value", "") + .text("Everything")); + + $('#send-channel') + .append($("") + .attr("value", "Add New Channel") + .text("Add New Channel")); + + $('#channels') + .append($("") + .attr("value", "") + .text("Everything")); + + for (var property in channels) { + if (channels.hasOwnProperty(property)) { + $('#send-channel') + .append($("") + .attr("value", property) + .text(property)); + + $('#channels') + .append($("") + .attr("value", property) + .text(property)); + } + } + + $("#channels").val(channel_filter); + $("#send-channel").val(cur_send_channel); +} + +function load_users() { + if (users_updating == true) return; + + users_updating = true; + + $.ajax({ + url: '/cgi-bin/meshchat?action=users&call_sign=' + call_sign + '&id=' + meshchat_id, + type: "GET", + dataType: "json", + context: this, + cache: false, + success: function(data, textStatus, jqXHR) + { + var html = ''; + if (data == null) return; + var count = 0; + for (var i = 0; i < data.length; i++) { + var date = new Date(0); + date.setUTCSeconds(data[i].epoch); + if ((epoch() - data[i].epoch) > 240) continue; + if ((epoch() - data[i].epoch) > 120) { + html += ''; + } else { + html += ''; + } + if (enable_video == 0) { + html += '' + data[i].call_sign + ''; + } else { + html += '' + data[i].call_sign + ''; + } + if (data[i].platform == 'node') { + html += '' + data[i].node + ''; + } else { + html += '' + data[i].node + ''; + } + html += '' + format_date(date) + ''; + html += ''; + + count++; + } + $('#users-table').html(html); + $('#users-count').html(count); + }, + complete: function(jqXHR, textStatus) { + //console.log( "users complete" ); + users_updating = false; + } + }); +} +>>>>>>> fff9980 (Initial pass at reorganization)