diff --git a/extend.php b/extend.php index 7188771..dac3f7e 100644 --- a/extend.php +++ b/extend.php @@ -18,7 +18,6 @@ use Flarum\Post\Post; use Flarum\Settings\Event\Saving; use FoF\GeoIP\Api\GeoIP; -use FoF\GeoIP\Api\Serializer\IPInfoSerializer; return [ (new Extend\Frontend('forum')) @@ -40,11 +39,7 @@ ->listen(Saving::class, Listeners\RemoveErrorsOnSettingsUpdate::class), (new Extend\ApiSerializer(PostSerializer::class)) - ->relationship('ip_info', function (PostSerializer $serializer, Post $model) { - if ($serializer->getActor()->can('viewIps', $model)) { - return $serializer->hasOne($model, IPInfoSerializer::class, 'ip_info'); - } - }), + ->relationship('ip_info', Api\AttachRelation::class), (new Extend\ApiController(Controller\ListPostsController::class)) ->addInclude('ip_info'), @@ -62,7 +57,9 @@ ->addInclude('posts.ip_info'), (new Extend\Settings()) - ->default('fof-geoip.service', 'ipapi'), + ->default('fof-geoip.service', 'ipapi') + ->default('fof-geoip.showFlag', false) + ->serializeToForum('fof-geoip.showFlag', 'fof-geoip.showFlag', 'boolval'), (new Extend\Routes('api')) ->get('/ip_info/{ip}', 'fof-geoip.api.ip_info', Api\Controller\ShowIpInfoController::class), diff --git a/js/src/admin/components/ExtensionSettingsPage.js b/js/src/admin/components/ExtensionSettingsPage.js index 1384e6c..732cacd 100644 --- a/js/src/admin/components/ExtensionSettingsPage.js +++ b/js/src/admin/components/ExtensionSettingsPage.js @@ -62,6 +62,12 @@ export default class GeoipSettingsPage extends ExtensionPage { placeholder: 1500, }) : []} + {this.buildSettingComponent({ + setting: 'fof-geoip.showFlag', + type: 'boolean', + label: app.translator.trans('fof-geoip.admin.settings.show_flag_label'), + help: app.translator.trans('fof-geoip.admin.settings.show_flag_help'), + })} {this.submitButton()} , diff --git a/js/src/forum/extenders/extendCommentPost.tsx b/js/src/forum/extenders/extendCommentPost.tsx new file mode 100644 index 0000000..c6c70db --- /dev/null +++ b/js/src/forum/extenders/extendCommentPost.tsx @@ -0,0 +1,20 @@ +import app from 'flarum/forum/app'; +import { extend } from 'flarum/common/extend'; +import ItemList from 'flarum/common/utils/ItemList'; +import CommentPost from 'flarum/forum/components/CommentPost'; +import type Mithril from 'mithril'; +import { getIPData } from '../helpers/IPDataHelper'; + +export default function extendCommentPost() { + extend(CommentPost.prototype, 'headerItems', function (items: ItemList) { + if (app.forum.attribute('fof-geoip.showFlag')) { + const ipInfo = this.attrs.post.ip_info?.(); + if (ipInfo) { + const { image } = getIPData(ipInfo); + if (image) { + items.add('country', image, 100); + } + } + } + }); +} diff --git a/js/src/forum/helpers/IPDataHelper.tsx b/js/src/forum/helpers/IPDataHelper.tsx index 4b1632e..128b51a 100644 --- a/js/src/forum/helpers/IPDataHelper.tsx +++ b/js/src/forum/helpers/IPDataHelper.tsx @@ -1,3 +1,4 @@ +import app from 'flarum/forum/app'; import IPInfo from '../models/IPInfo'; import getFlagEmojiUrl from '../util/getFlagEmojiUrl'; import Tooltip from 'flarum/common/components/Tooltip'; @@ -11,12 +12,21 @@ export const getThreat = (ipInfo: IPInfo) => { }; export const getFlagImage = (ipInfo: IPInfo) => { - if (ipInfo.countryCode() && ipInfo.countryCode().length > 1) { + if (ipInfo && ipInfo.countryCode() && ipInfo.countryCode().length > 1) { const url = getFlagEmojiUrl(ipInfo.countryCode()); + + const currentLocale = app.translator.getLocale() as string; + + // Create an instance of Intl.DisplayNames for displaying full country names + const displayNames = new Intl.DisplayNames([currentLocale], { type: 'region' }); + + // Get the full country name using the country code + const countryName = displayNames.of(ipInfo.countryCode()); + if (url) { return ( - - {ipInfo.countryCode()} + + {countryName} ); } diff --git a/js/src/forum/index.ts b/js/src/forum/index.ts index 00c1ace..4bdadfe 100644 --- a/js/src/forum/index.ts +++ b/js/src/forum/index.ts @@ -2,6 +2,7 @@ import app from 'flarum/forum/app'; import extendPostMeta from './extenders/extendPostMeta'; import extendBanIPModal from './extenders/extendBanIPModal'; import extendAccessTokensList from './extenders/extendAccessTokensList'; +import extendCommentPost from './extenders/extendCommentPost'; export { default as extend } from './extend'; @@ -9,4 +10,5 @@ app.initializers.add('fof/geoip', () => { extendPostMeta(); extendBanIPModal(); extendAccessTokensList(); + extendCommentPost(); }); diff --git a/resources/locale/en.yml b/resources/locale/en.yml index 133cde3..fcc01f1 100644 --- a/resources/locale/en.yml +++ b/resources/locale/en.yml @@ -23,6 +23,9 @@ fof-geoip: access_key_label: Access Key quota_label: Lookup quota + show_flag_label: Show country flag for each post + show_flag_help: Without disclosing the IP address, show the country flag of the IP address of the post author. + forum: alerts: ip_copied: Copied IP Address diff --git a/src/Api/AttachRelation.php b/src/Api/AttachRelation.php new file mode 100644 index 0000000..ba7e271 --- /dev/null +++ b/src/Api/AttachRelation.php @@ -0,0 +1,28 @@ +getActor()->can('viewIps', $post); + + return $serializer->hasOne($post, $viewIPs ? IPInfoSerializer::class : BasicIPInfoSerializer::class, 'ip_info'); + } +} diff --git a/src/Api/Serializer/BasicIPInfoSerializer.php b/src/Api/Serializer/BasicIPInfoSerializer.php new file mode 100644 index 0000000..6a02e64 --- /dev/null +++ b/src/Api/Serializer/BasicIPInfoSerializer.php @@ -0,0 +1,49 @@ + $ip->country_code, + ]; + } + + /** + * @param IPInfo $model + * + * @return string + */ + public function getId($model) + { + return hash('sha256', $model->address); + } +} diff --git a/src/Api/Serializer/IPInfoSerializer.php b/src/Api/Serializer/IPInfoSerializer.php index c5d0501..f52e7d3 100644 --- a/src/Api/Serializer/IPInfoSerializer.php +++ b/src/Api/Serializer/IPInfoSerializer.php @@ -11,14 +11,10 @@ namespace FoF\GeoIP\Api\Serializer; -use Flarum\Api\Serializer\AbstractSerializer; use FoF\GeoIP\Model\IPInfo; -use InvalidArgumentException; -class IPInfoSerializer extends AbstractSerializer +class IPInfoSerializer extends BasicIPInfoSerializer { - protected $type = 'ip_info'; - /** * @param IPInfo $ip * @@ -26,14 +22,9 @@ class IPInfoSerializer extends AbstractSerializer */ protected function getDefaultAttributes($ip): array { - if (!($ip instanceof IPInfo)) { - throw new InvalidArgumentException( - get_class($this).' can only serialize instances of '.IPInfo::class - ); - } + $attrs = parent::getDefaultAttributes($ip); - return [ - 'countryCode' => $ip->country_code, + $moreAttrs = [ 'zipCode' => $ip->zip_code, 'latitude' => $ip->latitude, 'longitude' => $ip->longitude, @@ -48,15 +39,7 @@ protected function getDefaultAttributes($ip): array 'createdAt' => $this->formatDate($ip->created_at), 'updatedAt' => $this->formatDate($ip->updated_at), ]; - } - /** - * @param IPInfo $model - * - * @return string - */ - public function getId($model) - { - return $model->address; + return array_merge($attrs, $moreAttrs); } }